00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __loaded__active_objects_h__
00021 #define __loaded__active_objects_h__
00022 using namespace std;
00023 #line 1 "active-objects.h++"
00024 #include <cstdio>
00025 #include <iostream>
00026 #include <string>
00027 #include <pthread.h>
00028 #include <stdlib.h>
00029 #include <assert.h>
00030 #include <vector>
00031 #include <queue>
00032 #include <deque>
00033 #include <time.h>
00034 #include "ao-scheduler.h"
00035 #include "ao-pool.h"
00036 using namespace std;
00037
00038 typedef enum{RevisitLater, Revisit, RevisitAfterIncoming, Done, Interrupt}
00039 elementResult;
00040
00193 template <class message>
00194 class ActiveObject: public Lock, protected Runnable
00195 {
00196 private:
00201 deque<message> incoming;
00202 protected:
00210 deque<message> handling;
00211 protected:
00217 ActiveObject(string name): Runnable(name)
00218 {
00219 active = false;
00220 changed = false;
00221 assert(aoPool);
00222 scheduler = aoPool->sunrise(name);
00223 assert(scheduler);
00224 };
00225 public:
00233 void push(message d)
00234 {
00235 Synchronized(this);
00236 push_internal(d);
00237 }
00242 void push(vector<message> v)
00243 {
00244 Synchronized(this);
00245 for(int i = 0 ; i<v.size();i++)
00246 push_internal(v[i]);
00247 }
00252 virtual ~ActiveObject()
00253 {
00254 if (active)
00255 cerr << "Active Object " << name << " is still active\n";
00256 if (scheduler)
00257 cerr << "Active Object " << name << " can still be activated\n";
00258 }
00259 private:
00266 void push_internal(message d)
00267 {
00268 assert(locked);
00269 incoming.push_back(d);
00270 activate();
00271 }
00272 protected:
00279 Scheduler * scheduler;
00280 public:
00286 virtual bool terminated()
00287 {
00288 return scheduler==NULL;
00289 }
00290 private:
00294 Lock updating_state;
00301 volatile bool active;
00310 volatile bool changed;
00345 void activate()
00346 {
00347 if (!scheduler) return;
00348 {
00349 Synchronized(updating_state);
00350 changed = true;
00351 if (active) return;
00352 active = true;
00353 }
00354 assert(scheduler);
00355 scheduler->start(this);
00356 }
00357 protected:
00370 elementResult deactivate()
00371 {
00372 #ifdef DEBUG_ACTIVATION
00373 cerr << "Deactivating " << name << endl;
00374 cerr.flush();
00375 #endif
00376 assert(scheduler);
00377 scheduler = false;
00378 if (aoPool)
00379 aoPool->sunset(name);
00380 return Done;
00381 }
00382 private:
00392 bool step()
00393 {
00394 bool transfer_needed = false;
00395 {
00396 Synchronized(updating_state);
00397 if (changed)
00398 {
00399 transfer_needed = true;
00400 changed = false;
00401 }
00402 }
00403 if (transfer_needed)
00409 {
00410 Synchronized(this);
00411 while(!incoming.empty())
00412 {
00413 handling.push_back(incoming.front());
00414 incoming.pop_front();
00415 }
00416 }
00426 if (handle() && scheduler)
00427 return true;
00428 {
00429 Synchronized(updating_state);
00430 if (changed) return true;
00431 active = false;
00432 return false;
00433 }
00434 }
00435 protected:
00454 virtual bool run(bool handle_as_many_as_possible)
00455 {
00456 if (handle_as_many_as_possible)
00457 {
00458 while(step()) {};
00459 return false;
00460 }
00461 else
00462 return step();
00463 }
00475 virtual bool handle()
00476 {
00477 if (handling.empty())
00478 return false;
00479 message f = handling.front();
00480 elementResult hr = handle(f);
00481 switch(hr)
00482 {
00483 case RevisitLater:
00484 handling.push_back(f);
00485 handling.pop_front();
00486
00487 break;
00488 case Done:
00489 handling.pop_front();
00490
00491 delete f;
00492 break;
00493 case Revisit:
00494 break;
00495 case Interrupt:
00496 return false;
00497 case RevisitAfterIncoming:
00498 push(f);
00499 handling.pop_front();
00500 break;
00501 default:
00502 assert(0);
00503 }
00504 bool t=!handling.empty();
00505 return t;
00506 }
00507
00522 virtual elementResult handle(message)
00523 {
00524 cerr << name << " lacks a handle(message) routine\n";
00525 assert(0);
00526 return Interrupt;
00527 }
00528 };
00529 #endif // __loaded__active_objects_h__