shared_instance implementation using C++ and RAII

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.
#include <memory>
#include <mutex>
template< typename t_type >
struct shared_instance
static std::shared_ptr< t_type > get_shared_instance()
static std::weak_ptr< t_type > weak;
static std::mutex mutex;
auto result = weak.lock();
if( nullptr == result )
std::unique_lock< std::mutex > lock mutex ;
result = weak.lock();
if( nullptr != result )
return result;
result = std::make_shared< t_type >();
weak = result;
return result;
;
template< typename t >
struct context
context()
: instance shared_instance< t >::get_shared_instance()
private: std::shared_ptr< t > instance;
;
I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).
c++ c++11 thread-safety singleton raii
add a comment |Â
up vote
3
down vote
favorite
I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.
#include <memory>
#include <mutex>
template< typename t_type >
struct shared_instance
static std::shared_ptr< t_type > get_shared_instance()
static std::weak_ptr< t_type > weak;
static std::mutex mutex;
auto result = weak.lock();
if( nullptr == result )
std::unique_lock< std::mutex > lock mutex ;
result = weak.lock();
if( nullptr != result )
return result;
result = std::make_shared< t_type >();
weak = result;
return result;
;
template< typename t >
struct context
context()
: instance shared_instance< t >::get_shared_instance()
private: std::shared_ptr< t > instance;
;
I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).
c++ c++11 thread-safety singleton raii
Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
â WooWapDaBug
Jan 29 at 12:58
yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations likecontext c1; /*some code here*/; context c2;c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
â cubber
Jan 29 at 14:16
so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
â cubber
Jan 29 at 14:23
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.
#include <memory>
#include <mutex>
template< typename t_type >
struct shared_instance
static std::shared_ptr< t_type > get_shared_instance()
static std::weak_ptr< t_type > weak;
static std::mutex mutex;
auto result = weak.lock();
if( nullptr == result )
std::unique_lock< std::mutex > lock mutex ;
result = weak.lock();
if( nullptr != result )
return result;
result = std::make_shared< t_type >();
weak = result;
return result;
;
template< typename t >
struct context
context()
: instance shared_instance< t >::get_shared_instance()
private: std::shared_ptr< t > instance;
;
I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).
c++ c++11 thread-safety singleton raii
I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.
#include <memory>
#include <mutex>
template< typename t_type >
struct shared_instance
static std::shared_ptr< t_type > get_shared_instance()
static std::weak_ptr< t_type > weak;
static std::mutex mutex;
auto result = weak.lock();
if( nullptr == result )
std::unique_lock< std::mutex > lock mutex ;
result = weak.lock();
if( nullptr != result )
return result;
result = std::make_shared< t_type >();
weak = result;
return result;
;
template< typename t >
struct context
context()
: instance shared_instance< t >::get_shared_instance()
private: std::shared_ptr< t > instance;
;
I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).
c++ c++11 thread-safety singleton raii
edited Feb 7 at 0:05
Jamalâ¦
30.1k11114225
30.1k11114225
asked Jan 28 at 16:16
cubber
184
184
Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
â WooWapDaBug
Jan 29 at 12:58
yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations likecontext c1; /*some code here*/; context c2;c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
â cubber
Jan 29 at 14:16
so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
â cubber
Jan 29 at 14:23
add a comment |Â
Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
â WooWapDaBug
Jan 29 at 12:58
yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations likecontext c1; /*some code here*/; context c2;c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
â cubber
Jan 29 at 14:16
so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
â cubber
Jan 29 at 14:23
Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
â WooWapDaBug
Jan 29 at 12:58
Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
â WooWapDaBug
Jan 29 at 12:58
yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like
context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instanceâ cubber
Jan 29 at 14:16
yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like
context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instanceâ cubber
Jan 29 at 14:16
so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
â cubber
Jan 29 at 14:23
so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
â cubber
Jan 29 at 14:23
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Non-Default Constructors:
Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.
template< typename t_type >
struct shared_instance
using t_factory = std::function<std::shared_ptr< t_type >()>;
static t_factory factory; // MUST be set before calling get_shared_instance
static std::shared_ptr< t_type > get_shared_instance()
...
assert(factory); // or throw, or return empty shared_ptr
result = factory(); // instead of make_shared
...
;
// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;
...
int main()
context<int> c; // not ok... haven't set factory yet!
// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...
context<int> c; // ok
I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:
template< typename t >
struct context
context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()
private:
std::shared_ptr< t > instance;
;
int main()
auto provider = instance_provider<int>( () return std::make_shared<int>(5); );
context<int> c(provider);
Further Considerations:
Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)
The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?
If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Non-Default Constructors:
Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.
template< typename t_type >
struct shared_instance
using t_factory = std::function<std::shared_ptr< t_type >()>;
static t_factory factory; // MUST be set before calling get_shared_instance
static std::shared_ptr< t_type > get_shared_instance()
...
assert(factory); // or throw, or return empty shared_ptr
result = factory(); // instead of make_shared
...
;
// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;
...
int main()
context<int> c; // not ok... haven't set factory yet!
// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...
context<int> c; // ok
I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:
template< typename t >
struct context
context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()
private:
std::shared_ptr< t > instance;
;
int main()
auto provider = instance_provider<int>( () return std::make_shared<int>(5); );
context<int> c(provider);
Further Considerations:
Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)
The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?
If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
add a comment |Â
up vote
2
down vote
accepted
Non-Default Constructors:
Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.
template< typename t_type >
struct shared_instance
using t_factory = std::function<std::shared_ptr< t_type >()>;
static t_factory factory; // MUST be set before calling get_shared_instance
static std::shared_ptr< t_type > get_shared_instance()
...
assert(factory); // or throw, or return empty shared_ptr
result = factory(); // instead of make_shared
...
;
// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;
...
int main()
context<int> c; // not ok... haven't set factory yet!
// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...
context<int> c; // ok
I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:
template< typename t >
struct context
context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()
private:
std::shared_ptr< t > instance;
;
int main()
auto provider = instance_provider<int>( () return std::make_shared<int>(5); );
context<int> c(provider);
Further Considerations:
Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)
The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?
If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Non-Default Constructors:
Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.
template< typename t_type >
struct shared_instance
using t_factory = std::function<std::shared_ptr< t_type >()>;
static t_factory factory; // MUST be set before calling get_shared_instance
static std::shared_ptr< t_type > get_shared_instance()
...
assert(factory); // or throw, or return empty shared_ptr
result = factory(); // instead of make_shared
...
;
// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;
...
int main()
context<int> c; // not ok... haven't set factory yet!
// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...
context<int> c; // ok
I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:
template< typename t >
struct context
context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()
private:
std::shared_ptr< t > instance;
;
int main()
auto provider = instance_provider<int>( () return std::make_shared<int>(5); );
context<int> c(provider);
Further Considerations:
Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)
The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?
If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.
Non-Default Constructors:
Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.
template< typename t_type >
struct shared_instance
using t_factory = std::function<std::shared_ptr< t_type >()>;
static t_factory factory; // MUST be set before calling get_shared_instance
static std::shared_ptr< t_type > get_shared_instance()
...
assert(factory); // or throw, or return empty shared_ptr
result = factory(); // instead of make_shared
...
;
// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;
...
int main()
context<int> c; // not ok... haven't set factory yet!
// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...
context<int> c; // ok
I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:
template< typename t >
struct context
context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()
private:
std::shared_ptr< t > instance;
;
int main()
auto provider = instance_provider<int>( () return std::make_shared<int>(5); );
context<int> c(provider);
Further Considerations:
Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)
The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?
If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.
answered Feb 6 at 20:05
user673679
1,042518
1,042518
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
add a comment |Â
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
â cubber
Feb 8 at 11:28
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
â cubber
Feb 8 at 11:31
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186204%2fshared-instance-implementation-using-c-and-raii%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
â WooWapDaBug
Jan 29 at 12:58
yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like
context c1; /*some code here*/; context c2;c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instanceâ cubber
Jan 29 at 14:16
so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
â cubber
Jan 29 at 14:23