I've been working on a little functional library. It's really small. I've focused on keeping it simple.
I plan on showing some of the features and hopefully we can discuss them. I'll explain as I reveal the features.
create function: #NOTE: The create function immediately destroys the object after its ctor has run.
1. Create a class object, using a separate thread:
1 2 3 4 5 6
|
class Declared;
int main()
{
cpm::Vault::create<Declared>();
return 0;
}
|
2. Create a class object, separate thread, constructor calls:
1 2 3 4 5 6 7
|
class Declared;
int main()
{
// Any constructor that Declared has, can be called.
cpm::Vault::create<Declared>('c', "++", 11);
return 0;
}
|
3. Create a class object, separate thread, heap or stack allocated:
1 2 3 4 5 6 7
|
class Declared;
int main()
{
// Class located on the new thread's stack:
cpm::Vault::create<Declared, cpm::stack>();
return 0;
}
|
4. Create a class object, separate thread, wait for it to finish
1 2 3 4 5 6 7
|
class Declared;
int main()
{
// Halts execution until the ctor of the class has finished.
cpm::Vault::create<Declared, cpm::halt>();
return 0;
}
|
5. Create a class object, separate thread, catch exceptions
1 2 3 4 5 6 7
|
class Declared;
int main()
{
// Makes sure exceptions are caught.
cpm::Vault::create<Declared, cpm::toss>();
return 0;
}
|
6. Create a class object, separate thread, combine flags
1 2 3 4 5 6 7
|
class Declared;
int main()
{
// skip, opposite of halt. heap, opposite of stack. drop, won't catch exceptions, opposite of toss.
cpm::Vault::create<Declared, cpm::skip | cpm::heap | cpm::drop>();
return 0;
}
|
That's all there is to the create function. Let's see what can happen in the ctor of Declared:
7. All objects built by create, need to inherit from cpm::Vault. They now have access to the Vault_ptr.
1 2 3 4 5
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr(new int(11)); // Deleted at end of scope, it's a smart ptr.
}
|
8. The object also gets a unique hash table
1 2 3 4 5 6
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr(new int(11));
store(ptr, "here"); // The pointer is stored here.
} // smart ptr NOT destroyed!
|
9. The object can fetch pointers as well
1 2 3 4 5 6
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr;
fetch(ptr, "here"); // The pointer is fetched from "here".
} // smart ptr NOT destroyed!
|
10. It can also "obtain" pointers
1 2 3 4 5 6
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr;
obtain(ptr, "here"); // Hash table "here" is erased
} // delete smart ptr.
|
11. Manual deletion of hash table stored pointers
1 2 3 4 5 6 7
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr(new int(11));
store(ptr, "here"); // The pointer is stored here.
destroy<int>("here");
} // smart ptr NOT destroyed! That'd cause double-free
|
12. Automated deletion of hash table contents
1 2 3 4 5 6 7 8 9
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr(new int(11));
store(ptr, "here"); // When the hash table goes out of scope, the integer is deleted automagically.
} // No smart pointer delete.
Declared::~Declared()
{
} // hash table goes out of scope hereafter.
|
Now you may be wondering:"What's the hash table used for anyway?". To answer this we look at the "build" function.
13. Propagation of the hash table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
class Declared;
class Another;
Declared::Declared()
{
Vault_ptr<int> ptr(new int(11));
store(ptr, "here"); // The pointer is stored in "here".
build<Another>(); // Just like create, but shares the hash table instead of creating a new one.
// flags cpm::drop (no exception catching), cpm::toss (for exceptions), cpm::stack (stack allocation), cpm::heap (new the object).
} // smart ptr NOT destroyed!
Another::Another()
{
Vault_ptr<int> ptr(obtain("here"));
} // smart pointer destroys the integer
|
Now 2 objects have the same hash table, and they can access them independently of one another. They can share data.
When both objects finish running, a reference counter ticks to 0. When that happens, the hash table and all of its content is deleted safely and successfully.
14. Everything is array friendly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
class Declared;
class Another;
Declared::Declared()
{
Vault_ptr<int[]> ptr(new int[32]);
store(ptr, "here"); // The pointer is stored in "here".
build<Another>(); // Just like create, but shares the hash table instead of creating a new one.
// flags cpm::drop (no exception catching), cpm::toss (for exceptions), cpm::stack (stack allocation), cpm::heap (new the object).
} // smart ptr NOT destroyed!
Another::Another()
{
Vault_ptr<int[]> ptr(fetch("here"));
} // smart pointer doesn't destroy.
|
When both objects are out of scope (destroyed), the hash table gets destroyed. The array will be correctly deallocated.
15. Manual deletion of hash table arrays
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
class Declared;
class Another;
Declared::Declared()
{
Vault_ptr<int[]> ptr(new int[32]);
store(ptr, "here"); // The pointer is stored in "here".
build<Another>();
} // smart ptr NOT destroyed!
Another::Another()
{
Vault_ptr<int[]> ptr(fetch("here"));
destroy<int[0]>("here"); // ptr now becomes an invalid pointer. The hash table is now cleaned from "here".
// Memory is now freed.
} // smart pointer doesn't destroy.
|
16. Super-safe
1 2 3 4 5 6 7 8
|
class Declared;
Declared::Declared()
{
Vault_ptr<int[]> ptr(new int[32]);
store(ptr, "here");
obtain(ptr, "here");
destroy<int[0]>("here"); // Deletes a nullptr, safe.
} // smart ptr destroyed!
|
17. Creator Control
1 2 3 4 5 6 7 8 9 10
|
class Declared;
Declared::Declared()
{
fall(); // Allows thread from main() to continue, because it used the "halt" flag.
}
int main()
{
cpm::Vault::create<Declared, cpm::halt>();
return 0;
}
|
18. Creator Safety
1 2 3 4 5 6 7 8 9
|
class Declared;
Declared::Declared()
{
} // Allows main() thread to continue, when the hash_table goes out of scope.
int main()
{
cpm::Vault::create<Declared, cpm::halt>();
return 0;
}
|
19. Exception friendlyness
1 2 3 4 5 6 7 8 9 10
|
class Declared;
Declared::Declared()
{
throw std::string().at(10); // throws, hash table deallocated, main() thread unpaused.
}
int main()
{
cpm::Vault::create<Declared, cpm::halt | cpm::toss>();
return 0;
}
|
20. Vault_ptr operators
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr0(new int);
Vault_ptr<int> ptr1(fetch("here"));
Vault_ptr<int> ptr2(obtain("here"));
Vault_ptr<int> ptr3(find("here"));
Vault_ptr<int[]> ptr4(new int[2]);
Vault_ptr<std::vector<int>> ptr5(new std::vector<int>);
*ptr0; // Direct member access
ptr0 = new int;
ptr1 = fetch("here");
fetch(ptr1, "here");
ptr2 = obtain("here");
obtain(ptr2, "here");
ptr3 = find("here");
ptr4[1]; // Element access
ptr5->push_back(0);
}
int main()
{
cpm::Vault::create<Declared, cpm::halt | cpm::drop>();
return 0;
}
|
21. Vault_ptr special function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
class Declared;
Declared::Declared()
{
Vault_ptr<int> ptr(new int); // delete at end of scope.
build<Declared>(ptr.transfer());
// ptr can still be used, but it will not delete at end of scope
(*ptr)++;
}
Declared::Declared(int *a)
{
Vault_ptr<int> ptr(a); // Deletes a at end of scope.
store(ptr, "here"); // Won't delete until reference counter ticks 0
}
int main()
{
cpm::Vault::create<Declared, cpm::halt>();
return 0;
}
|
So that's basically it. It allows one to create endlessly many "chains" of hash tables with the 'create' function.
Each chain can have endlessly many objects tied to it, all knowing the same hash table.
It's like a localized global storage system, which is dynamic, and above all, safe.
The items in the hash table are correctly deleted when the chain dies. Everything is array friendly as well.
I'd like to hear your thoughts or opinions on this little functional library. :)