How to Safely (And Easily) Count *All* Instances of a Class Within My Program

How can I safely (and easily) count *all* instances of a class within my program?

Think of the static class variable as a global variable which is just in the namespace of the class. Incrementing or doing other things with it will not have any side effects on other code, i.e. your constructors and other operators will behave exactly as before.

I.e., you are right: Just increment in all constructors and decrement in the destructor.


Of course, as George pointed out, if you want to have it multithreading safe, you need to add some multithreading safe code around the access to your counter variable (for example some mutex). Or as Steven pointed out, you might also use atomic increment/decrement instructions (but the usage will depend on the platform). Those would be a lot faster. Though, you have to be careful because in some cases that wont work in multi-processor environments. You can use Boost's atomic_count to be on the safe side.

Counting instances of a class?

You could consider using a class attribute to provide a counter. Each instance needs only to ask for the next value. They each get something unique. Eg:

from itertools import count

class Obj(object):
_ids = count(0)

def __init__(self):
self.id = next(self._ids)

How to Count Number of Instances of a Class

Since static variables are initialized only once, and they're shared between all instances, you can:

class MyClass {

private static int counter;

public MyClass() {
//...
counter++;
}

public static int getNumOfInstances() {
return counter;
}
}

and to access the static field counter you can use MyClass.getNumOfInstances()

Read more about static fields in the JLS - 8.3.1.1. static Fields:

If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).

Note that counter is implicitly set to zero

Count instances of the class

You can holds global static counter in your program.

This is a simple thread safe solution:

class MyClass
{
static int counter = 0;

public MyClass()
{
Interlocked.Increment(ref counter);
}

~MyClass()
{
Interlocked.Decrement(ref counter);
}
}

also take a look at the following similar question - Count number of objects of class type within class method

Simplest way to count instances of an object

Have a "counted object" class that does the proper reference counting in its constructor(s) and destructor, then derive your objects that you want to track from it. You can then use the curiously recurring template pattern to get distinct counts for any object types you wish to track.

// warning: pseudo code

template <class Obj>
class CountedObj
{
public:
CountedObj() {++total_;}
CountedObj(const CountedObj& obj) {++total_;}
~CountedObj() {--total_;}

static size_t OustandingObjects() {return total_;}

private:
static size_t total_;
};

class MyClass : private CountedObj<MyClass>
{};

How to keep track of class instances?

One way to keep track of instances is with a class variable:

class A(object):
instances = []

def __init__(self, foo):
self.foo = foo
A.instances.append(self)

At the end of the program, you can create your dict like this:

foo_vars = {id(instance): instance.foo for instance in A.instances}

There is only one list:

>>> a = A(1)
>>> b = A(2)
>>> A.instances
[<__main__.A object at 0x1004d44d0>, <__main__.A object at 0x1004d4510>]
>>> id(A.instances)
4299683456
>>> id(a.instances)
4299683456
>>> id(b.instances)
4299683456

Printing all instances of a class

I see two options in this case:

Garbage collector

import gc
for obj in gc.get_objects():
if isinstance(obj, some_class):
dome_something(obj)

This has the disadvantage of being very slow when you have a lot of objects, but works with types over which you have no control.

Use a mixin and weakrefs

from collections import defaultdict
import weakref

class KeepRefs(object):
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self))

@classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst

class X(KeepRefs):
def __init__(self, name):
super(X, self).__init__()
self.name = name

x = X("x")
y = X("y")
for r in X.get_instances():
print r.name
del y
for r in X.get_instances():
print r.name

In this case, all the references get stored as a weak reference in a list. If you create and delete a lot of instances frequently, you should clean up the list of weakrefs after iteration, otherwise there's going to be a lot of cruft.

Another problem in this case is that you have to make sure to call the base class constructor. You could also override __new__, but only the __new__ method of the first base class is used on instantiation. This also works only on types that are under your control.

Edit: The method for printing all instances according to a specific format is left as an exercise, but it's basically just a variation on the for-loops.

How can I count the number of elements with same class?

With jQuery you can use

$('#main-div .specific-class').length

otherwise in VanillaJS (from IE8 included) you may use

document.querySelectorAll('#main-div .specific-class').length;

Get instance count of a specific class in Objective-C/IOS

Per request, I've mocked up a category that will keep count of allocated objects using method swizzling and a singleton. This was a quick mock up, so there are a few issues with it (one being that initializing anything that is contained within the storage class will cause an infinite loop). Mind you, this is for keeping track of many objects and should not be used in a production environment. The best methodology overall is to use the instruments tool.

#import "NSObject+Initializer.h"
#import <objc/runtime.h>

@interface ObjectCounter : NSObject

+ (instancetype)sharedObjectCounter;
@property (strong, nonatomic) NSMutableDictionary *objectCounterDictionary;

@end

@implementation ObjectCounter

+ (instancetype)sharedObjectCounter
{
static ObjectCounter *objectCounter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
objectCounter = [ObjectCounter new];
objectCounter.objectCounterDictionary = [NSMutableDictionary new];
});
return objectCounter;
}

@end

@implementation NSObject (Initializer)

+ (NSNumber *)initializedCount
{
NSLog(@"Dict: %@", [ObjectCounter sharedObjectCounter].objectCounterDictionary);
return [ObjectCounter sharedObjectCounter].objectCounterDictionary[NSStringFromClass([self class])];
}

+ (id)alloc_swizzled
{
NSLog(@"Swizzled");
NSString *className = NSStringFromClass([self class]);
if (![className isEqualToString:NSStringFromClass([NSMutableDictionary class])] && ![className isEqualToString:NSStringFromClass([ObjectCounter class])]) {
ObjectCounter *counter = [ObjectCounter sharedObjectCounter];
NSMutableDictionary *objectDictionary = counter.objectCounterDictionary;
NSNumber *count = objectDictionary[className];
count = count ? @(count.integerValue + 1) : @0;
objectDictionary[className] = count;
}

return [self alloc_swizzled];
}

+ (void)load
{

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];

SEL originalSelector = @selector(alloc);
SEL swizzledSelector = @selector(alloc_swizzled);

Method originalMethod = class_getClassMethod(class, originalSelector);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));

if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}

Can you find all classes in a package using reflection?

Due to the dynamic nature of class loaders, this is not possible. Class loaders are not required to tell the VM which classes it can provide, instead they are just handed requests for classes, and have to return a class or throw an exception.

However, if you write your own class loaders, or examine the classpaths and it's jars, it's possible to find this information. This will be via filesystem operations though, and not reflection. There might even be libraries that can help you do this.

If there are classes that get generated, or delivered remotely, you will not be able to discover those classes.

The normal method is instead to somewhere register the classes you need access to in a file, or reference them in a different class. Or just use convention when it comes to naming.

Addendum: The Reflections Library will allow you to look up classes in the current classpath. It can be used to get all classes in a package:

 Reflections reflections = new Reflections("my.project.prefix");

Set<Class<? extends Object>> allClasses =
reflections.getSubTypesOf(Object.class);


Related Topics



Leave a reply



Submit