Files
secondo/Algebras/Temporal2/StreamValve.cpp

215 lines
6.2 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
implemenation of streamvalves
*/
#include <iostream>
#include "StreamValve.h"
#include <cstdlib>
#include <unistd.h>
using namespace std;
using namespace boost::interprocess;
namespace temporal2algebra {
StreamValve::StreamValve() {
std::cout << "StreamValve()\n";
}
StreamValve::~StreamValve() {
std::cout << "~StreamValve()\n";
}
void StreamValve::waitForSignal() {
std::cout << "StreamValve::waitForSignal()\n";
}
void StreamValve::sendHasReadSucceeded(bool success) {
std::cout << "StreamValve::sendHasReadSucceeded("<< success << ")\n";
}
RandomStreamValve::RandomStreamValve(int min_wait_sec, int max_wait_sec)
: min_wait_sec(min_wait_sec),
max_wait_sec(max_wait_sec) {
std::cout << "RandomStreamValve ("
<< min_wait_sec << ", "
<< max_wait_sec << ")\n";
};
RandomStreamValve::~RandomStreamValve() {
std::cout << "~RandomStreamValve()\n";
}
void RandomStreamValve::waitForSignal() {
std::cout << "RandomStreamValve::waitForSignal()\n";
int random_integer = rand() %
(max_wait_sec - min_wait_sec + 1) + min_wait_sec;
std::cout << "will sleep for " << random_integer << "secs\n";
sleep(random_integer);
std::cout << "done sleeping " << random_integer << "secs\n";
}
RemoteStreamValve* RemoteStreamValve::create(std::string controllerId) {
std::cout << "RemoteStreamValve::create(" << controllerId << ")\n";
// if we have a dangling named_mutex this will remove it, but:
// if there is another process actually using the same,
// we'll be in trouble
bool res_remove = named_mutex::remove(("mutex_" + controllerId).c_str());
std::cout << "res_remove = " << res_remove << std::endl;
bool shm_remove = shared_memory_object::remove(
("shm_" + controllerId).c_str());
std::cout << "shm_remove = " << shm_remove << std::endl;
return new RemoteStreamValve(controllerId);
}
// This may throw!
RemoteStreamValve::RemoteStreamValve(std::string controllerId) :
controllerId(controllerId),
mutex(create_only, ("mutex_" + controllerId).c_str()),
shm(create_only //only create
,("shm_" + controllerId).c_str() //name
,read_write //read-write mode
)
{
std::cout << "RemoteStreamValve (" << controllerId << ")\n";
//try...
shm.truncate(sizeof(RemoteValveControl));
region = mapped_region(shm, read_write);
void* addr = region.get_address();
controlPtr = new (addr) RemoteValveControl;
};
RemoteStreamValve::~RemoteStreamValve() {
std::cout << "~RemoteStreamValve()\n";
bool res_remove = named_mutex::remove(("mutex_" + controllerId).c_str());
std::cout << "res_remove = " << res_remove << std::endl;
bool shm_remove = shared_memory_object::remove(
("shm_" + controllerId).c_str());
std::cout << "shm_remove = " << shm_remove << std::endl;
}
int RemoteStreamValve::advance(
const std::string& controllerId,
int advanceCount) {
std::cout << "RemoteStreamValve::advance("
<< controllerId << ", "
<< advanceCount << ")\n";
int num_read = 0;
try{
// code duplication ahead (c.f. StreamValve.cpp/.h)
shared_memory_object shm
(open_only
,("shm_" + controllerId).c_str()
,read_write
);
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
void * addr = region.get_address();
RemoteValveControl* control = static_cast<RemoteValveControl*>(addr);
cout << "StreamNext_vm: control->num_request: "
<< control->num_request << "\n"
<< "StreamNext_vm: control->num_done: "
<< control->num_done << "\n";
{
scoped_lock<interprocess_mutex> lock(control->mutex);
while (1) {
// There's work left in the queue,
// wait until processed and get actual read items
if (control->num_request) {
control->cond_wait_for_read_result.wait(lock);
continue;
}
// Empty queue, but no result -> put some work in the queue
if (!control->request_processed) {
control->num_request = advanceCount;
control->num_done = 0; // should be zero anyway
control->cond_wait_for_signal.notify_all();
control->cond_wait_for_read_result.wait(lock);
continue;
}
// empty request queue but result received:
control->request_processed = false;
num_read = control->num_done;
control->num_done = 0;
break;
}
control->cond_wait_for_signal.notify_all();
} // end scope for lock
}
catch(interprocess_exception &ex){
std::cout << ex.what() << std::endl;
num_read = -1;
}
return num_read;
}
void RemoteStreamValve::waitForSignal() {
std::cout << "RemoteStreamValve::waitForSignal()\n";
std::cout << "ToDo: wait for remote Controller "
<< controllerId
<< ". For now just sleep a bit\n";
// sleep(1);
{ // scope for lock
scoped_lock<interprocess_mutex> lock(controlPtr->mutex);
while (1) {
if (!controlPtr->num_request) {
controlPtr->cond_wait_for_signal.wait(lock);
continue;
}
break;
}
}
std::cout << "done sleeping\n";
}
void RemoteStreamValve::sendHasReadSucceeded(bool success) {
std::cout << "RemoteStreamValve::sendHasReadSucceeded("
<< success << ")\n";
{ // scope for lock
scoped_lock<interprocess_mutex> lock(controlPtr->mutex);
if (success) {
controlPtr->num_request--;
controlPtr->num_done++;
} else {
controlPtr->num_request=0;
}
if (controlPtr->num_request <= 0) {
controlPtr->request_processed = true;
}
controlPtr->cond_wait_for_read_result.notify_all();
}
}
} /* namespace temporal2algebra */