1

I have a singleton "manager" object which gets instantiated at process-start and lives for the duration of the process (effectively).

This object creates multiple temporary tasks (which are themselves objects) during it's lifetime, using "new" and later destroys them with "delete". These two operations are carried out in two different functions - one function is called by external objects to perform a specific task, the other function is a callback that is called when the task has been completed, hence the task object is then destroyed.

Due to the fact that the task objects are not created/destroyed in a scope that is "temporary" (e.g. a single member function), am I wasting my time trying to apply RAII in this instance? Or is there a mechanism I should be using to deal with this?

Regards, Richard.

riph72
  • 11
  • 1
  • 1
    The problem with singletons in your case is that there is no certain point when they should get destructed (without doing some extra work). Could you please provide a code sample of what you have tried, to illustrate your question? – πάντα ῥεῖ Oct 27 '13 at 11:14
  • As @g-makulik said, also see http://stackoverflow.com/questions/469597/destruction-order-of-static-objects-in-c – OMGtechy Oct 27 '13 at 11:16
  • @g-makulik - this is not what he asks. See my comment to your answer. – Asaf Oct 27 '13 at 11:26

2 Answers2

3

You could use smart pointers (e.g. shared_ptr). The singleton should hold a container of pointers to these tasks (e.g. a map), and remove it from the vector when completed.

For example (not compiling, just for illustration):

class MySingleton
{
    typedef std::shared_ptr<Task> TaskPtr;
    std::map<int, TaskPtr> m_tasks;

    StartTask()
    {
        TaskPtr task = std::make_shared<Task>();
        m_tasks[index] = task;
        ...
    }

    OnTaskEnd()
    {
        TaskPtr task = m_tasks[index];
        m_tasks.remove(index);
        taskCompletedHandler(task);

        // Unless taskCompletedHandler copies task, it will be destroyed when this leaves scope.
    }
Asaf
  • 4,317
  • 28
  • 48
  • 1
    That's actually remarkably similar to how we do it - the only real differences being we use a list rather than a map, and perform new/delete manually, rather than using a smart pointer. So with that in mind - I'm not sure where the advantage of the smart pointer is, in your example, because we still have to effectively do things manually? – riph72 Oct 31 '13 at 16:52
  • 1
    @riph72 - Which things do you do manually here? There's no delete in this code (and no new, but that's irrelevant). A callback can do nothing, in which case the task will be deleted, or keep a copy of the task, in which case it will not be deleted (until you decide to do so). All you have here is the logic of removing the task from the map. This is exactly how you apply RAII in this case. – Asaf Nov 03 '13 at 09:55
0

Your pointer to sub tasks is stored somewhere between the first creating and second destroying function.

Change that pointer to a unique_ptr and it will reflect the fact that it owns the lifetime of the resource. Documenting ownership with types, prevents resource handle duplication, and can make your code more safe.

A more advanced technique would be to replace the 'return resource' stage entirely with RAII. Return a unique_ptr to some dqta or token from the crearion function that implicitly calls the destroying function when reset: push the RAII up a level of abstraction. Rhis is not always easy, desireable or useful, but is still worth considering.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524