Search code examples
c++boostboost-function

Boost function assignment throws exception


Boost::function is throwing me exceptions one out of ten times when I try to assign one function1 to another function1.

Task is a typedef for boost::function1<void, void*>.

Here is the specific code:

    // the Task object sent in as Task task
    void Sleeper(void* arg)
    {
        int32_t sleepTime = *(int32_t*)arg;

        SleepCurrentThread((int32_t)sleepTime);
    }

    struct ThreadInfo
    {
        ThreadInfo() : mState(DETACHED), mTask(NULL), mArg(NULL)
        { }

        ThreadState mState;
        Task mTask;
        void* mArg;
    };

    Thread::Thread(Task task, void* arg, IMemoryAllocator& allocator, ILogManager& logger) : mAllocator(allocator), mLogger(logger)
    {
        mThreadInfo = (ThreadInfo*) mAllocator.Allocate(sizeof(ThreadInfo));  // simnple heap allocation

        mThreadInfo->mArg = arg;
        mThreadInfo->mState = Thread::RUNNING;
        mThreadInfo->mTask = task;     //<--------- throws... sometimes


        mHandle = _CreateThread(&Run, (void*)mThreadInfo);
        if (!mHandle)
            Detach();


    }

I specificly tracked it down in the boost function_template.hpp to the assignment operator, on this code, where it ultimately throws:

// Assignment from another BOOST_FUNCTION_FUNCTION
    BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
    {
      if (&f == this)
        return *this;

      this->clear();
      BOOST_TRY {
        this->assign_to_own(f);        // <--- throws, and then line below re-throws
      } BOOST_CATCH (...) {
        vtable = 0;
        BOOST_RETHROW;
      }
      BOOST_CATCH_END
      return *this;
    }

Why is this? Is there anything easily spotted that is wrong with my code? Is there anything else needed?

Thanks

EDIT: I know I will be asked to use boost::threads, but I'm trying out my own wrapper around win32/pthread, (for fun)


Solution

  • Your struct has a non-trivial constructor, but you don't call it. It leaves the Task member uninitialized. To initialize it, either allocate the whole object with new, or use placement new to initialize it as follows:

        void *mem = mAllocator.Allocate(sizeof(ThreadInfo));  // simnple heap allocation
        mThreadInfo = new(mem) ThreadInfo; // placement new
    
        mThreadInfo->mArg = arg;
        mThreadInfo->mState = Thread::RUNNING;
        mThreadInfo->mTask = task;
    

    Placement new constructs an object in an already allocated raw (uninitialized) memory.