notepad_commandqueue.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: notepad_commandqueue.cpp
00003  */
00004 
00005 /*
00006  * This file is part of notepad.
00007  *
00008  * notepad is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * notepad is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2010 IREX Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #include "notepad_commandqueue.h"
00028 #include "log.h"
00029 
00030 
00031 namespace notepad
00032 {
00033 
00034     
00035 CmdQueue::CmdQueue()
00036     : thread(0)
00037     , current_command(0)
00038     , stop_flag(false)
00039     , flush_flag(false)
00040 {
00041 }
00042 
00043 CmdQueue::~CmdQueue()
00044 {
00045     empty_queue();
00046 }
00047 
00048 gpointer CmdQueue::thread_func(gpointer args) // gtk c to c++ wrap
00049 {
00050     g_assert(args);
00051     CmdQueue* thiz = reinterpret_cast<CmdQueue *>(args);
00052     return thiz->non_static_thread_func();
00053 }
00054 
00055 // Worker thread
00056 gpointer CmdQueue::non_static_thread_func()
00057 {
00058     LOGPRINTF("entry");
00059 
00060     while (true)
00061     {
00062         LOGPRINTF("waiting for semaphore");
00063         sem.p();
00064 
00065         if (stop_flag)
00066         {
00067             MutexLocker ml(&queue_mutex);
00068             LOGPRINTF("break here");
00069             empty_queue();
00070             sem.set(0);
00071             stop_flag = false;
00072             break;
00073         }
00074         if (flush_flag)
00075         {
00076             MutexLocker ml(&queue_mutex);
00077             LOGPRINTF("flushing queue");
00078             empty_queue();
00079             sem.set(0);
00080             flush_flag = false;
00081             continue;
00082         }
00083 
00084         current_command = the_queue.front();
00085         current_command->execute();
00086         {
00087             MutexLocker ml(&queue_mutex);
00088             the_queue.pop_front();
00089         }
00090         current_command = 0;
00091         g_thread_yield(); // give room for mainthread
00092     }
00093 
00094     LOGPRINTF("exit");
00095     return 0;
00096 }
00097 
00098 void CmdQueue::empty_queue() 
00099 {
00100     LOGPRINTF("entry");
00101 
00102     CommandQueueIter idx = the_queue.begin();
00103     // dont flush the current command
00104     if (current_command != 0) idx++; // pass command currently being executed
00105     while (idx != the_queue.end())
00106     {
00107         delete *idx;
00108         idx = the_queue.erase(idx);
00109         idx++;
00110     }
00111     the_queue.clear();
00112     g_assert(the_queue.empty());
00113     LOGPRINTF("exit");
00114 }
00115 
00116 void CmdQueue::flush() // interuppts the worker thread to empty queue
00117 {
00118     LOGPRINTF("entry");
00119     if (thread == 0)
00120     {
00121         return;
00122     }
00123     flush_flag = true;
00124     sem.v();
00125 
00126     LOGPRINTF("exit");
00127 }
00128 
00129 bool CmdQueue::start() // starts the worker thread
00130 {
00131     LOGPRINTF("entry");
00132     if (thread != 0)
00133     {
00134         // The thread has been started.
00135         return false;
00136     }
00137 
00138     thread = g_thread_create(thread_func, this, TRUE, 0);
00139     LOGPRINTF("exit");
00140     return thread != 0;
00141 }
00142 
00143 void CmdQueue::stop()
00144 {
00145     LOGPRINTF("entry");
00146     if (thread == 0)
00147     {
00148         return;
00149     }
00150     stop_flag = true;
00151     sem.v();
00152 
00153     // Wait for worker thread to die.
00154     g_thread_join(thread);
00155     LOGPRINTF("thread is stopped");
00156 
00157     // Set the thread to be NULL
00158     thread = 0;
00159     LOGPRINTF("exit");
00160 }
00161 
00162 void CmdQueue::add(Command* new_command)
00163 {
00164     LOGPRINTF("entry");
00165     g_assert(thread); // cmd can only be added when an workerthread is active
00166 
00167     // if being flushed wait for flush to ready
00168     while (flush_flag) 
00169     {
00170         g_thread_yield(); 
00171     }
00172 
00173     // Append task to the end of the task queue.
00174     {
00175         MutexLocker ml(&queue_mutex); //guard
00176         the_queue.push_back(new_command);
00177         sem.v();
00178     }
00179     LOGPRINTF("exit");
00180 }
00181 
00182 
00183 } // namespace
00184 
Generated by  doxygen 1.6.2-20100208