I have a base class, Token. It has no implementation and as such acts as a marker interface. This is the type that will be used by callers.
{
Token t = startJob(jobId);
// ... (tasks)
// t falls out of scope, destructors are called
}
I have a derived class, LockToken. It wraps around a mutex and insures the lock is acquired during construction and released during destruction. The startJob method is a factory method in the sense that it decides whether to return a Token (providing no locking) or a LockToken (providing locking).
Token startJob(int jobId)
{
return (jobId>0) ? LockToken() : Token() ;
}
When startJob would return a base instance (a Token), everything works well. In the other case (jobId>0), there is a copy made of the derived instance to the base instance. In other workds, a different Token is copy-constructed from the LockToken and the original LockToken falls out of scope too soon, releasing the lock inside the scope of startJob.
How do I get out of this? Can I change startJob so that it returns or outputs a truly covariant Token (meaning it may be a LockToken)?
You are returning a Token by value. That means that you are not returning a LockToken, but rather a Token copy constructed from your LockToken instance.
A much better approach would be to use boost::shared_ptr. That way your clients can copy things around without needing to worry about deletion. Something like this:
Note that you no longer need a Token class that does nothing, and the LockToken class is now an implementation detail that is entirely hidden from clients, giving you scope for doing all kinds of other things when the Token goes out of scope.