Common shutdown functions - safely shut down

As detailed in the example programs found under samples/url_sample_extended or samples/customdbsample_extended, it is necessary to create two threads for the scheduling and update mechanisms.

The threads are usually in a loop and call the schedule() and performUpdate() functions:

void updateTask( void *myData )
{
        const MyDcaContext *myDcaContext = 
                reinterprete_cast< MyDcaContext *>( myData );

        if( myDcaContext ) {
                while( !myDcaContext->inShutdown ) {
                        dca::UpdateResults myUpdateResults;

                        dca::FunctionResult fr = 
                                myDcaContext->updateModule.performUpdate( false, 
                                        myUpdateResults );
                                        
                        if( !fr ) {
                                // got an error... try to re-initialize the DCA
                                return;
                        }
                        // enumerate myUpdateResults...
                        sleep( 1000 ); // wait 1 second until next call to performUpdate()
                }
        }
}
// subscriber to catch the events of the DcaInstance::schedule function
class MyScheduleEventSubscriber : public dca::ScheduleEventSubscriberIntf
{
public:
        MyScheduleEventSubscriber() { }
        virtual ~MyScheduleEventSubscriber() { }
        
        virtual void onEvent( dca::ScheduleActionType actionType, 
                dca::ScheduleModuleId moduleId, const std::string& version, 
                const std::string& text )
        {
                // Handle the event...
        }
};

void schedulerTask( void *myData )
{
        const MyDcaContext *myDcaContext = 
                reinterprete_cast< MyDcaContext *>( myData );

        if( myDcaContext ) {
                while( !myDcaContext->inShutdown ) {
                        MyScheduleEventSubscriber mySubscriber;
                        dca::FunctionResult fr = 
                                myDcaContext->dcaInstance.schedule( &mySubscriber );
                        if( !fr ) {
                                // got an error... try to re-initialize the DCA
                                return;
                        }
                        sleep( 5000 ); // wait some seconds until next call to schedule()
                }
        }
}

Both threads must have an end condition. In this case, the class MyContext contains a variable inShutdown. This variable is set to true in the destructor of MyContext.

The MyContext destructor also calls the functions dca::UpdateModule::cancelUpdate() and dca::DcaInstance::signal() before the dca::DcaInstance objects are destroyed. The cancelUpdate() function cancels all currently active downloads and uploads, while the signal() function aborts all other long-lasting processes.

The following code sample demonstrates this:

class MyDcaContext
{
public:

        MyDcaContext() : inShutDown (false)
        { }

        virtual ~MyDcaContext()
        {
                // signal DCA worker threads to shutdown
                inShutDown = true;

                 // this cancels the download or update task if it is currently running
                updateModule.cancelUpdate();

                // this cancels all long-lasting functions and forces them to return immediately
                // such as database merge processes...
                dcaInstance.signal( DCA_SIG_ABORT );

                // ...
                // wait for worker threads to finish
                // ...

                // all other DCA objects are destructed in reverse construction order
        }

        // initialize the DCA objects
        virtual bool Init();

        // Construction order is important!
        // the DCA instance must always be created first.
        dca::DcaInstance dcaInstance;
        dca::InitData initData;
        dca::License license;
        dca::UpdateModule updateModule;
        dca::DbConnectionData connectData;
        dca::DbConnection dbConnection;
        dca::UrlClassification urlClassification;
        dca::UrlDbClassifier urlDbClassifier;

        volatile bool inShutDown;
        ...
};

After both functions have been successfully called, it is necessary to wait for the worker threads to end before shutting down the dca::DcaInstance objects.


Generated on 26 Sep 2016 for dca_interface by  doxygen 1.6.1