Explorar el Código

Refactored a bit to solve circular references in module includes.

Fixed some compiler errors.


git-svn-id: https://svn.microneil.com/svn/SNF4CGP/trunk@16 59e8e3e7-56fa-483b-b4b4-fa6ab0af3dfc
master
madscientist hace 15 años
padre
commit
90075fc40c

+ 49
- 0
SNF4CGP/Command.hpp Ver fichero

@@ -0,0 +1,49 @@
// SNF4CGP/Command.hpp
// Copyright (C) 2009 ARM Research Labs, LLC
// See www.armresearch.com for more information.
//
// The Command class describes what CGP is asking us to do.
#ifndef IncludedCommand
#define IncludedCommand
#include <string>
using namespace std;
class Command { // Parsed Command Objects
public:
enum CommandType { // Commands have these types:
UNKNOWN, // We don't know this command.
QUIT, // It is time to stop the app.
WAKE, // Report the app is now awake.
INTF, // Report the interface version.
FILE // Scan this file.
};
unsigned int Number; // Commands have a serial number
CommandType Type; // Commands have a type.
string Data; // Other command data goes here.
Command::Command() : // Ordinary constructor.
Number(0),
Type(UNKNOWN),
Data("") {
}
Command::Command(const Command& R) : // Copy constructor.
Number(R.Number),
Type(R.Type) {
Data = R.Data;
}
Command& operator=(const Command& R) { // We need an assignment operator.
Number = R.Number;
Type = R.Type;
Data = R.Data;
return (*this);
}
};
#endif

+ 12
- 13
SNF4CGP/ExecutiveProcess.cpp Ver fichero

@@ -4,7 +4,7 @@
#include "ExecutiveProcess.hpp"
#include "../SNF4CGP/CodeDweller/faults.hpp"
#include "../CodeDweller/faults.hpp"
#include <iostream>
@@ -22,27 +22,27 @@ RuntimeCheck CheckOutputProccessorWasConstructed("ExecutiveProcess::initializeOu
RuntimeCheck CheckOutputProcessorWasStarted("ExecutiveProcess::initializeOutput() Check(Output->isRunning())");
void ExecutiveProcess::initializeOutput() {
CheckJobPoolNotNull(0 != Jobs);
try { Output = new OutputProcessor(*Jobs); } catch(...) {}
CheckOutputProcessorWasConstructed(0 != Output);
try { Output->start() } catch(...) {}
CheckOutputProcessorWasStarted(Output->isRunning());
Output.init(Jobs);
}
void ExecutiveProcess::initializeJobPool() {
Jobs = new JobPool(ConfigInfo
Jobs.init(ConfigInfo, Output);
}
void ExecutiveProcess::initializeWorkerPool() {
Workers.init();
}
void ExecutiveProcess::shutdownWorkerPool() {
Workers.stop();
}
void ExecutiveProcess::shutdownJobPool() {
Jobs.stop();
}
void ExecutiveProcess::shutdownOutput() {
Output.stop();
}
void ExecutiveProcess::dispatchCommand(Command& C) { // Job + Worker + Command; go!
@@ -52,12 +52,12 @@ void ExecutiveProcess::dispatchCommand(Command& C) {
W.doJob(J);
}
ExecutiveProcess::ExecutiveProcess(string& Version, string& Config) : // Simple construction.
ExecutiveProcess::ExecutiveProcess(const string& Version, const string& Config) : // Simple construction.
VersionInfo(Version),
ConfigInfo(Config),
QuitJobNumber(0) {}
~ExecutiveProcess::ExecutiveProcess() { // Deal with uncerimoneous shutdowns.
ExecutiveProcess::~ExecutiveProcess() { // Deal with uncerimoneous shutdowns.
}
void ExecutiveProcess::doStartup() { // Startup happens in this sequence.
@@ -68,14 +68,13 @@ void ExecutiveProcess::doStartup() {
void ExecutiveProcess::doProcessing() { // Command processing happens here.
Command C;
C.CommandType = WAKE; // Create the WAKE command to announce
C.Type = Command::WAKE; // Create the WAKE command to announce
C.Data = VersionInfo; // that we are alive (and who we are)
dispatchCommand(C); // and dispatch a job with it.
// Then process all incoming commands:
InputProcessor& I = *Input; // Convenient handle for input processor.
for(;0 == QuitJobNumber;) { // Loop until we have a QUIT job.
C = I.getCommand(); // Get a command from the input.
if(QUIT == C.CommandType) QuitJobNumber = C.Number; // QUIT command means it's time to stop.
C = Input.getCommand(); // Get a command from the input.
if(Command::QUIT == C.Type) QuitJobNumber = C.Number; // QUIT command means it's time to stop.
else dispatchCommand(C); // Dispatch a job for all other commands.
}
}

+ 3
- 2
SNF4CGP/ExecutiveProcess.hpp Ver fichero

@@ -13,6 +13,7 @@
#include "WorkerPool.hpp"
#include "InputProcessor.hpp"
#include "OutputProcessor.hpp"
#include "Command.hpp"
#include <string>
@@ -37,11 +38,11 @@ class ExecutiveProcess {
void shutdownJobPool();
void shutdownOutput();
void dispatchCommand(Command C); // Job + Worker + Command; go!
void dispatchCommand(Command& C); // Job + Worker + Command; go!
public:
ExecutiveProcess(string& Version, string& Config); // Simple construction. The d'tor needs
ExecutiveProcess(const string& Version, const string& Config); // Simple construction. The d'tor needs
~ExecutiveProcess(); // to deal with uncerimoneous shutdowns.
void doStartup(); // The main thread calls these in sequence.

+ 14
- 0
SNF4CGP/InputProcessor.cpp Ver fichero

@@ -1,3 +1,17 @@
// SNF4CGP/InputProcessor.cpp
// Copyright (C) 2009 ARM Research Labs, LLC.
// See www.armresearch.com for more information.
#include "InputProcessor.hpp"
using namespace std;
//// InputProcessor ////////////////////////////////////////////////////////////
Command InputProcessor::getCommand() { // How to get/parse a command
// get a line from cin
// parse the number
// parse the type
// parse the remaining data
// return the command
}

+ 1
- 13
SNF4CGP/InputProcessor.hpp Ver fichero

@@ -8,22 +8,10 @@
#ifndef IncludedInputProcessor
#define IncludedInputProcessor
#include <string>
#include "Command.hpp"
using namespace std;
struct Command { // Parsed Command Objects
unsigned int Number; // Commands have a serial number
enum CommandType { // Commands have these types:
UNKNOWN, // We don't know this command.
QUIT, // It is time to stop the app.
WAKE, // Report the app is now awake.
INTF, // Report the interface version.
FILE // Scan this file.
} Type; // Here is where we keep it.
string Data; // Other command data goes here.
};
class InputProcessor { // Here is the InputProcessor object.
public:

+ 9
- 7
SNF4CGP/JobPool.hpp Ver fichero

@@ -22,17 +22,19 @@
#ifndef IncludedJobPool
#define IncludedJobPool
#include "../SNF4CGP/SNFMulti/SNFMulti.hpp"
#include "../SNF4CGP/CodeDweller/threading.hpp"
#include "../SNFMulti/SNFMulti.hpp"
#include "../CodeDweller/threading.hpp"
#include "InputProcessor.hpp"
#include "ScannerPool.hpp"
#include "Command.hpp"
#include <string>
#include <vector>
using namespace std;
class ScannerPool;
class OutputProcessor;
class Job { // SNF4CGP Job instance.
private:
ScannerPool& Scanners; // Knows where to get scanners.
@@ -60,7 +62,7 @@ class Job {
public:
Job(ScannerPool& S, OutputProcessor O); // Construct with important links.
~Job(); // Cleanup when destructing.
void setCommand(Command C); // Assign a command for this job.
void setCommand(Command& C); // Assign a command for this job.
void doIt(); // Get the job done.
string& Responses(); // Read the job's report.
void clear(); // Cleanup for the next command.
@@ -82,10 +84,10 @@ class JobPool {
public:
JobPool(); // Basic construction.
~JobPool(); // Safe cleanup on destruction.
init(string Configuration, OutputProcessor& O); // Get ready to allocate jobs.
void init(string Configuration, OutputProcessor& O); // Get ready to allocate jobs.
Job& grab(); // Get a fresh job object.
void drop(Job& J); // Drop a used job object.
stop(); // Shutdown and clean up.
void stop(); // Shutdown and clean up.
};
#endif

+ 4
- 3
SNF4CGP/OutputProcessor.cpp Ver fichero

@@ -3,8 +3,9 @@
// See www.armresearch.com for more information.
#include "OutputProcessor.hpp"
#include "JobPool.hpp"
#include "../SNF4CGP/CodeDweller/faults.hpp"
#include "../CodeDweller/faults.hpp"
using namespace std;
@@ -14,7 +15,7 @@ const ThreadState OutputProcessor::PostingResponses("Posting");
OutputProcessor::OutputProcessor() : // Constructor sets up the basics.
Thread(OutputProcessor::Type, "Output"), // Name the thread.
RecycledJobs(0), // No job pool yet.
RecycledJobs_(0), // No job pool yet.
isTimeToStop(false) { // Not time to stop.
}
@@ -49,7 +50,7 @@ void OutputProcessor::handleJob(Job& J) {
CurrentThreadState(PostingResponses);
cout << J.Responses();
J.clear();
RecycledJobs.drop(J);
RecycledJobs().drop(J);
}
void OutputProcessor::myTask() { // This is how we do it.

+ 5
- 4
SNF4CGP/OutputProcessor.hpp Ver fichero

@@ -11,15 +11,16 @@
#ifndef IncludedOutputProcessor
#define IncludedOutputProcessor
#include "JobPool.hpp"
#include "../CodeDweller/threading.hpp"
class JobPool; // Yes there is a JobPool class.
class Job; // Yes there is a Job class.
class OutputProcessor : private Thread { // Process job outputs.
private:
JobPool* Jobs_; // Where we put our recycled jobs.
JobPool& Jobs(); // Safe access to jobs pool.
JobPool* RecycledJobs_; // Where we put our recycled jobs.
JobPool& RecycledJobs(); // Safe access to jobs pool.
ProductionQueue<Job*> CompletedJobs; // Input queue for jobs to process.
bool isTimeToStop; // Flag for when we need to stop.

+ 6
- 4
SNF4CGP/ScannerPool.hpp Ver fichero

@@ -9,8 +9,7 @@
#ifndef IncludedScannerPool
#define IncludedScannerPool
#include "../SNF4CGP/SNFMulti/SNFMulti.hpp"
#include "../SNF4CGP/CodeDweller/threading.hpp"
#include "../CodeDweller/threading.hpp"
#include <string>
@@ -18,6 +17,9 @@ using namespace std;
// Constructing a scanner is essentially constructing an snf_EngineHandler in a wrapper.
class snf_RulebaseHandler; // These classes exists.
class snf_EngineHandler;
class Scanner { // SNF Scanner instance for the pool
private:
snf_RulebaseHandler& Rulebase_; // Rulebase the scanner uses.
@@ -40,8 +42,8 @@ class ScannerPool {
public:
ScannerPool(); // Constructed with Rulebase config.
~ScannerPool(); // Cleans up when destroyed.
init(string Configuration); // Get ready to provide scanners.
stop(); // Shutdown and clean up.
void init(string Configuration); // Get ready to provide scanners.
void stop(); // Shutdown and clean up.
Scanner& grab(); // Provides a Scanner from the pool.
void drop(Scanner& S); // Returns a Scanner to the pool.
};

+ 32
- 31
SNF4CGP/WorkerPool.cpp Ver fichero

@@ -3,8 +3,9 @@
// See www.armresearch.com for more information.
#include "WorkerPool.hpp"
#include "JobPool.hpp"
#include "../SNF4CGP/CodeDweller/faults.hpp"
#include "../CodeDweller/faults.hpp"
using namespace std;
@@ -20,7 +21,7 @@ Worker::Worker(WorkerPool& W) :
myJob_(0) {
}
virtual Worker::~Worker() { // Cleanup on the way down.
Worker::~Worker() { // Cleanup on the way down.
try { stop(); }
catch(...) {}
}
@@ -31,7 +32,7 @@ bool Worker::isJob() {
RuntimeCheck CheckForValidJobPointer("Worker::myJob() Check(0 != myJob_)");
Job& myJob() { // Safe access to myJob.
Job& Worker::myJob() { // Safe access to myJob.
CheckForValidJobPointer(0 != myJob_);
return(*myJob_);
}
@@ -48,7 +49,7 @@ void Worker::doJob(Job& J) {
LogicCheck CheckForNoJobsAtStop("Worker::stop() Check(false == isJob())");
void Worker::stop() { // Stop the worker thread.
ScopeMutext CallTheBall(Busy); // Don't stop while busy or vv.
ScopeMutex CallTheBall(Busy); // Don't stop while busy or vv.
if(false == TimeToStop) { // Do this only once.
CheckForNoJobsAtStop(false == isJob());
TimeToStop = true; // It is time to stop.
@@ -81,38 +82,19 @@ void Worker::myTask() {
//// WorkerPool ////////////////////////////////////////////////////////////////
/*
class WorkerPool { // Worker pools look like this...
private:
Mutex AllocationMutex; // Worker pool allocation control.
ProductionQueue<Worker*> RecycledWorkers; // Where do recyceled workers go.
unsigned int AllocatedWorkers; // Count of workers to clean up.
bool Started; // True if we're ready to go.
public:
WorkerPool(); // Set startup defaults.
~WorkerPool(); // Cleanup if needed.
void init(); // Start making workers.
Worker& grab(); // Give me a worker to use.
void drop(Worker& W); // Take this worker back.
void stop(); // Destroy all workers and stop.
};
*/
WorkerPool::WorkerPool() :
WorkerPool::WorkerPool() : // Simple construction.
AllocatedWorkers(0),
Started(false) {
}
WorkerPool::~WorkerPool() {
WorkerPool::~WorkerPool() { // Cleanup on the way out.
try { stop(); }
catch(...) {}
}
void WorkerPool::init() { // Initialize the worker pool.
Worker& FirstWorker = makeWorker(); // Make the first worker and
drop(FirstWorker); // drop it into the pool.
Worker* FirstWorker = makeWorker(); // Make the first worker and
drop(*FirstWorker); // drop it into the pool.
Started = true; // We are now initialized.
}
@@ -120,13 +102,15 @@ Worker* WorkerPool::makeWorker() {
Worker* NewWorker = 0;
NewWorker = new Worker(*this); // Allocate the worker.
++AllocatedWorkers; // If successful count it.
return Worker; // Return a reference.
return NewWorker; // Return a reference.
}
RuntimeCheck CheckForValidGrabbedWorker("WorkerPool:grab() Check(0 != GrabbedWorker)");
LogicCheck CheckGrabOnlyWhenStarted("WorkerPool::grab() Check(Started)");
RuntimeCheck CheckForValidGrabbedWorker("WorkerPool::grab() Check(0 != GrabbedWorker)");
Worker& WorkerPool::grab() { // Grab a worker from the pool.
ScopeMutex Busy(AllocationMutex);
CheckGrabOnlyWhenStarted(Started);
Worker* GrabbedWorker = 0;
if(0 < RecycledWorkers.size()) GrabbedWorker = RecycledWorkers.take(); // Prefer to use recycled workers.
else GrabbedWorker = makeWorker(); // Make new ones if needed.
@@ -134,8 +118,25 @@ Worker& WorkerPool::grab() {
return (*GrabbedWorker);
}
void WorkerPool::drop(Worker& W) {
// Note that drop() does not use the AllocationMutex. This decouples (somewhat) drop operations from allocation
// operations and improves the performance potential. Since only one thread will ever use the AllocationMutex
// it should never see contention -- it is essentially a safety device in case some later modification gets
// things wrong or some other event occurs that causes a conflict.
void WorkerPool::drop(Worker& W) { // Drop a worker into the pool.
RecycledWorkers.give(&W);
}
void WorkerPool::killWorkerFromPool() { // Destroy and count workers.
Worker* WorkerToKill = 0;
WorkerToKill = RecycledWorkers.take(); // Take a worker from the pool.
WorkerToKill->stop(); // Stop the worker thread.
delete WorkerToKill; // Destroy it.
--AllocatedWorkers; // Count each one.
}
void WorkerPool::stop() {
void WorkerPool::stop() { // Shutdown the pool (reclaim all)
ScopeMutex Busy(AllocationMutex); // No grabbing.
while(0 < AllocatedWorkers) killWorkerFromPool(); // Kill each worker in the pool.
Started = false; // We're not alive now.
}

+ 4
- 5
SNF4CGP/WorkerPool.hpp Ver fichero

@@ -15,10 +15,9 @@
#ifndef IncludedWorkerPool
#define IncludedWorkerPool
#include "../SNF4CGP/CodeDweller/threading.hpp"
#include "JobPool.hpp"
#include "../CodeDweller/threading.hpp"
class Job;
class WorkerPool; // There will be a worker pool.
class Worker : private Thread { // This is a worker thread.
@@ -27,7 +26,7 @@ class Worker : private Thread {
ProductionGateway StoppingPoint; // Thread stops here and waits.
Mutex Busy; // Busy state protection.
bool TimeToStop; // stop() has been called.
void doWork(); // Get a job done.
bool doWork(); // Get a job done.
void myTask(); // Task for the thread. (my loop).
Job* myJob_; // The job to do (or 0 to stop).
bool isJob(); // Job pointer check.
@@ -42,7 +41,6 @@ class Worker : private Thread {
const static ThreadType Type;
const static ThreadState Waiting;
const static ThreadState Working;
};
class WorkerPool { // Worker pools look like this...
@@ -53,6 +51,7 @@ class WorkerPool {
bool Started; // True if we're ready to go.
Worker* makeWorker(); // Make and count workers.
void killWorkerFromPool(); // Kill a worker from the pool.
public:
WorkerPool(); // Set startup defaults.

Cargando…
Cancelar
Guardar