summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2017-10-31 14:35:41 +0100
committerGitHub <noreply@github.com>2017-10-31 14:35:41 +0100
commitd28ab5ee8f5611a99a8f673cf35983adff62c338 (patch)
tree797dc114da4587bf89812784acb45bab7f3c5b08
parent11ce8e98af18a65f208f92c8988eee78714e3767 (diff)
parent10b63f93aeba3f62b8360e422abc2116b76d7b40 (diff)
Merge pull request #3943 from vespa-engine/toregge/use-standard-locks-in-fastos
Toregge/use standard locks in fastos
-rw-r--r--fastos/src/tests/job.h9
-rw-r--r--fastos/src/tests/processtest.cpp23
-rw-r--r--fastos/src/tests/thread_bounce_test.cpp28
-rw-r--r--fastos/src/tests/thread_joinwait_test.cpp6
-rw-r--r--fastos/src/tests/thread_mutex_test.cpp21
-rw-r--r--fastos/src/tests/thread_test_base.hpp74
-rw-r--r--fastos/src/tests/threadtest.cpp91
-rw-r--r--fastos/src/tests/typetest.cpp3
-rw-r--r--fastos/src/vespa/fastos/CMakeLists.txt2
-rw-r--r--fastos/src/vespa/fastos/app.cpp2
-rw-r--r--fastos/src/vespa/fastos/app.h7
-rw-r--r--fastos/src/vespa/fastos/cond.h165
-rw-r--r--fastos/src/vespa/fastos/mutex.h64
-rw-r--r--fastos/src/vespa/fastos/ringbuffer.h12
-rw-r--r--fastos/src/vespa/fastos/socketevent.cpp18
-rw-r--r--fastos/src/vespa/fastos/socketevent.h4
-rw-r--r--fastos/src/vespa/fastos/thread.cpp109
-rw-r--r--fastos/src/vespa/fastos/thread.h25
-rw-r--r--fastos/src/vespa/fastos/unix_app.cpp10
-rw-r--r--fastos/src/vespa/fastos/unix_cond.cpp49
-rw-r--r--fastos/src/vespa/fastos/unix_cond.h42
-rw-r--r--fastos/src/vespa/fastos/unix_ipc.cpp97
-rw-r--r--fastos/src/vespa/fastos/unix_ipc.h2
-rw-r--r--fastos/src/vespa/fastos/unix_mutex.cpp18
-rw-r--r--fastos/src/vespa/fastos/unix_mutex.h44
-rw-r--r--fastos/src/vespa/fastos/unix_process.cpp36
-rw-r--r--fastos/src/vespa/fastos/unix_process.h4
-rw-r--r--fnet/src/vespa/fnet/fnet.h2
28 files changed, 276 insertions, 691 deletions
diff --git a/fastos/src/tests/job.h b/fastos/src/tests/job.h
index a5b84fa0f9c..1d35ec95270 100644
--- a/fastos/src/tests/job.h
+++ b/fastos/src/tests/job.h
@@ -2,6 +2,9 @@
#pragma once
+#include <mutex>
+#include <condition_variable>
+
enum JobCode
{
PRINT_MESSAGE_AND_WAIT3SEC,
@@ -28,9 +31,8 @@ private:
public:
JobCode code;
char *message;
- FastOS_Mutex *mutex;
- FastOS_Cond *condition;
- FastOS_BoolCond *boolcondition;
+ std::mutex *mutex;
+ std::condition_variable *condition;
FastOS_ThreadInterface *otherThread, *ownThread;
double *timebuf;
double average;
@@ -45,7 +47,6 @@ public:
message(nullptr),
mutex(nullptr),
condition(nullptr),
- boolcondition(nullptr),
otherThread(nullptr),
ownThread(nullptr),
timebuf(nullptr),
diff --git a/fastos/src/tests/processtest.cpp b/fastos/src/tests/processtest.cpp
index 11e1307027d..cd6839fd0aa 100644
--- a/fastos/src/tests/processtest.cpp
+++ b/fastos/src/tests/processtest.cpp
@@ -17,15 +17,14 @@ public:
static int _allocCount;
static int _successCount;
static int _failCount;
- static FastOS_Mutex *_counterLock;
+ static std::mutex *_counterLock;
MyListener (const char *title)
: _title(title),
_receivedBytes(0)
{
- _counterLock->Lock();
- _allocCount++;
- _counterLock->Unlock();
+ std::lock_guard<std::mutex> guard(*_counterLock);
+ _allocCount++;
}
virtual ~MyListener ()
@@ -34,14 +33,13 @@ public:
const int correctByteCount = 16;
- _counterLock->Lock();
+ std::lock_guard<std::mutex> guard(*_counterLock);
if(_receivedBytes == (isStdout ? correctByteCount : 0))
_successCount++;
else
_failCount++;
_allocCount--;
- _counterLock->Unlock();
}
void OnReceiveData (const void *data, size_t length) override
@@ -62,7 +60,7 @@ public:
int MyListener::_allocCount = 0;
int MyListener::_successCount = 0;
int MyListener::_failCount = 0;
-FastOS_Mutex *MyListener::_counterLock = nullptr;
+std::mutex *MyListener::_counterLock = nullptr;
class ThreadRunJob : public FastOS_Runnable
@@ -122,7 +120,7 @@ private:
// or not.
bool _gotMessage;
int _receivedMessages;
- FastOS_Mutex *_counterLock;
+ std::mutex *_counterLock;
bool _isChild;
public:
ProcessTest ()
@@ -156,9 +154,8 @@ public:
// We only have the counter lock if we are the parent process.
if(_counterLock != nullptr)
{
- _counterLock->Lock();
- _receivedMessages++;
- _counterLock->Unlock();
+ std::lock_guard<std::mutex> guard(*_counterLock);
+ _receivedMessages++;
}
}
@@ -219,7 +216,7 @@ public:
const int numLoops = 100;
const int numEachTime = 40;
- MyListener::_counterLock = new FastOS_Mutex();
+ MyListener::_counterLock = new std::mutex;
char testHeader[200];
strcpy(testHeader, "Process Test");
@@ -381,7 +378,7 @@ public:
TestHeader ("IPC Test");
const char *childProgram = _argv[1];
- _counterLock = new FastOS_Mutex();
+ _counterLock = new std::mutex;
int i;
for(i=0; i<30; i++)
diff --git a/fastos/src/tests/thread_bounce_test.cpp b/fastos/src/tests/thread_bounce_test.cpp
index bf94f3e1aab..423221d55cb 100644
--- a/fastos/src/tests/thread_bounce_test.cpp
+++ b/fastos/src/tests/thread_bounce_test.cpp
@@ -14,8 +14,10 @@ class Thread_Bounce_Test : public ThreadTestBase
TestHeader("Bounce Test");
FastOS_ThreadPool pool(128 * 1024);
- FastOS_Cond cond1;
- FastOS_Cond cond2;
+ std::mutex mutex1;
+ std::condition_variable cond1;
+ std::mutex mutex2;
+ std::condition_variable cond2;
Job job1;
Job job2;
FastOS_Time checkTime;
@@ -28,7 +30,9 @@ class Thread_Bounce_Test : public ThreadTestBase
job2.code = BOUNCE_CONDITIONS;
job1.otherjob = &job2;
job2.otherjob = &job1;
+ job1.mutex = &mutex1;
job1.condition = &cond1;
+ job2.mutex = &mutex2;
job2.condition = &cond2;
job1.ownThread = pool.NewThread(this, static_cast<void *>(&job1));
@@ -44,28 +48,28 @@ class Thread_Bounce_Test : public ThreadTestBase
left = static_cast<int>(checkTime.MilliSecsToNow());
}
- cond1.Lock();
+ mutex1.lock();
cnt1 = job1.bouncewakeupcnt;
- cond1.Unlock();
- cond2.Lock();
+ mutex1.unlock();
+ mutex2.lock();
cnt2 = job2.bouncewakeupcnt;
- cond2.Unlock();
+ mutex2.unlock();
cntsum = cnt1 + cnt2;
Progress(lastcntsum != cntsum, "%d bounces", cntsum);
lastcntsum = cntsum;
}
job1.ownThread->SetBreakFlag();
- cond1.Lock();
+ mutex1.lock();
job1.bouncewakeup = true;
- cond1.Signal();
- cond1.Unlock();
+ cond1.notify_one();
+ mutex1.unlock();
job2.ownThread->SetBreakFlag();
- cond2.Lock();
+ mutex2.lock();
job2.bouncewakeup = true;
- cond2.Signal();
- cond2.Unlock();
+ cond2.notify_one();
+ mutex2.unlock();
pool.Close();
Progress(true, "Pool closed.");
diff --git a/fastos/src/tests/thread_joinwait_test.cpp b/fastos/src/tests/thread_joinwait_test.cpp
index 05ab1627334..7153a05f836 100644
--- a/fastos/src/tests/thread_joinwait_test.cpp
+++ b/fastos/src/tests/thread_joinwait_test.cpp
@@ -25,11 +25,11 @@ class Thread_JoinWait_Test : public ThreadTestBase
Job jobs[testThreads];
- FastOS_Mutex jobMutex;
+ std::mutex jobMutex;
// The mutex is used to pause the first threads until we have created
// the last one.
- jobMutex.Lock();
+ jobMutex.lock();
for(i=0; i<lastThreadNum; i++)
{
@@ -68,7 +68,7 @@ class Thread_JoinWait_Test : public ThreadTestBase
}
}
- jobMutex.Unlock();
+ jobMutex.unlock();
if((variant & 1) != 0)
{
diff --git a/fastos/src/tests/thread_mutex_test.cpp b/fastos/src/tests/thread_mutex_test.cpp
index b8ac575038b..d49cf37163d 100644
--- a/fastos/src/tests/thread_mutex_test.cpp
+++ b/fastos/src/tests/thread_mutex_test.cpp
@@ -25,10 +25,11 @@ class Thread_Mutex_Test : public ThreadTestBase
{
int i;
Job jobs[MUTEX_TEST_THREADS];
- FastOS_Mutex *myMutex=nullptr;
+ std::mutex *myMutex=nullptr;
- if(usingMutex)
- myMutex = new FastOS_Mutex();
+ if(usingMutex) {
+ myMutex = new std::mutex;
+ }
for(i=0; i<MUTEX_TEST_THREADS; i++)
{
@@ -117,7 +118,7 @@ class Thread_Mutex_Test : public ThreadTestBase
FastOS_ThreadPool pool(128*1024);
Job job;
- FastOS_Mutex mtx;
+ std::mutex mtx;
job.code = HOLD_MUTEX_FOR2SEC;
job.result = -1;
@@ -135,28 +136,28 @@ class Thread_Mutex_Test : public ThreadTestBase
for(int i=0; i<5; i++)
{
- lockrc = mtx.TryLock();
+ lockrc = mtx.try_lock();
Progress(!lockrc, "We should not get the mutex lock just yet (%s)",
lockrc ? "got it" : "didn't get it");
if(lockrc) {
- mtx.Unlock();
+ mtx.unlock();
break;
}
}
FastOS_Thread::Sleep(2000);
- lockrc = mtx.TryLock();
+ lockrc = mtx.try_lock();
Progress(lockrc, "We should get the mutex lock now (%s)",
lockrc ? "got it" : "didn't get it");
if(lockrc)
- mtx.Unlock();
+ mtx.unlock();
Progress(true, "Attempting to do normal lock...");
- mtx.Lock();
+ mtx.lock();
Progress(true, "Got lock. Attempt to do normal unlock...");
- mtx.Unlock();
+ mtx.unlock();
Progress(true, "Unlock OK.");
}
diff --git a/fastos/src/tests/thread_test_base.hpp b/fastos/src/tests/thread_test_base.hpp
index 5305b132d3c..7966e95b369 100644
--- a/fastos/src/tests/thread_test_base.hpp
+++ b/fastos/src/tests/thread_test_base.hpp
@@ -2,13 +2,17 @@
#pragma once
+#include <chrono>
+
static volatile int64_t number;
#define INCREASE_NUMBER_AMOUNT 10000
+using namespace std::chrono_literals;
+
class ThreadTestBase : public BaseTest, public FastOS_Runnable
{
private:
- FastOS_Mutex printMutex;
+ std::mutex printMutex;
public:
ThreadTestBase(void)
@@ -19,9 +23,8 @@ public:
void PrintProgress (char *string) override
{
- printMutex.Lock();
+ std::lock_guard<std::mutex> guard(printMutex);
BaseTest::PrintProgress(string);
- printMutex.Unlock();
}
void Run (FastOS_ThreadInterface *thread, void *arg) override;
@@ -93,8 +96,10 @@ void ThreadTestBase::Run (FastOS_ThreadInterface *thread, void *arg)
{
int result;
- if(job->mutex != nullptr)
- job->mutex->Lock();
+ std::unique_lock<std::mutex> guard;
+ if(job->mutex != nullptr) {
+ guard = std::unique_lock<std::mutex>(*job->mutex);
+ }
result = static_cast<int>(number);
@@ -107,8 +112,7 @@ void ThreadTestBase::Run (FastOS_ThreadInterface *thread, void *arg)
FastOS_Thread::Sleep(1000);
}
- if(job->mutex != nullptr)
- job->mutex->Unlock();
+ guard = std::unique_lock<std::mutex>();
job->result = result; // This marks the end of the thread
@@ -132,26 +136,23 @@ void ThreadTestBase::Run (FastOS_ThreadInterface *thread, void *arg)
case WAIT_FOR_THREAD_TO_FINISH:
{
- if(job->mutex)
- job->mutex->Lock();
+ std::unique_lock<std::mutex> guard;
+ if (job->mutex != nullptr) {
+ guard = std::unique_lock<std::mutex>(*job->mutex);
+ }
if(job->otherThread != nullptr)
job->otherThread->Join();
- if(job->mutex)
- job->mutex->Unlock();
break;
}
case WAIT_FOR_CONDITION:
{
- job->condition->Lock();
-
+ std::unique_lock<std::mutex> guard(*job->mutex);
job->result = 1;
-
- job->condition->Wait();
- job->condition->Unlock();
-
+ job->condition->wait(guard);
+ guard.unlock();
job->result = 0;
break;
@@ -160,25 +161,25 @@ void ThreadTestBase::Run (FastOS_ThreadInterface *thread, void *arg)
case BOUNCE_CONDITIONS:
{
while (!thread->GetBreakFlag()) {
- job->otherjob->condition->Lock();
- job->otherjob->bouncewakeupcnt++;
- job->otherjob->bouncewakeup = true;
- job->otherjob->condition->Signal();
- job->otherjob->condition->Unlock();
-
- job->condition->Lock();
- while (!job->bouncewakeup)
- job->condition->TimedWait(1);
- job->bouncewakeup = false;
- job->condition->Unlock();
+ {
+ std::lock_guard<std::mutex> guard(*job->otherjob->mutex);
+ job->otherjob->bouncewakeupcnt++;
+ job->otherjob->bouncewakeup = true;
+ job->otherjob->condition->notify_one();
+ }
+ std::unique_lock<std::mutex> guard(*job->mutex);
+ while (!job->bouncewakeup) {
+ job->condition->wait_for(guard, 1ms);
+ }
+ job->bouncewakeup = false;
}
break;
}
case TEST_ID:
{
- job->mutex->Lock(); // Initially the parent threads owns the lock
- job->mutex->Unlock(); // It is unlocked when we should start
+ job->mutex->lock(); // Initially the parent threads owns the lock
+ job->mutex->unlock(); // It is unlocked when we should start
FastOS_ThreadId currentId = FastOS_Thread::GetCurrentThreadId();
@@ -192,18 +193,19 @@ void ThreadTestBase::Run (FastOS_ThreadInterface *thread, void *arg)
case WAIT2SEC_AND_SIGNALCOND:
{
FastOS_Thread::Sleep(2000);
- job->condition->Signal();
+ job->condition->notify_one();
job->result = 1;
break;
}
case HOLD_MUTEX_FOR2SEC:
{
- job->mutex->Lock();
- FastOS_Thread::Sleep(2000);
- job->mutex->Unlock();
- job->result = 1;
- break;
+ {
+ std::lock_guard<std::mutex> guard(*job->mutex);
+ FastOS_Thread::Sleep(2000);
+ }
+ job->result = 1;
+ break;
}
case WAIT_2_SEC:
diff --git a/fastos/src/tests/threadtest.cpp b/fastos/src/tests/threadtest.cpp
index 81ea234fb97..b0b64697129 100644
--- a/fastos/src/tests/threadtest.cpp
+++ b/fastos/src/tests/threadtest.cpp
@@ -5,18 +5,18 @@
#include "thread_test_base.hpp"
#include <vespa/fastos/time.h>
#include <cstdlib>
+#include <chrono>
#define MUTEX_TEST_THREADS 6
#define MAX_THREADS 7
-
class ThreadTest : public ThreadTestBase
{
int Main () override;
void WaitForXThreadsToHaveWait (Job *jobs,
int jobCount,
- FastOS_Cond *condition,
+ std::mutex &mutex,
int numWait)
{
Progress(true, "Waiting for %d threads to be in wait state", numWait);
@@ -26,16 +26,15 @@ class ThreadTest : public ThreadTestBase
{
int waitingThreads=0;
- condition->Lock();
-
- for(int i=0; i<jobCount; i++)
{
- if(jobs[i].result == 1)
- waitingThreads++;
+ std::lock_guard<std::mutex> guard(mutex);
+ for(int i=0; i<jobCount; i++)
+ {
+ if(jobs[i].result == 1)
+ waitingThreads++;
+ }
}
- condition->Unlock();
-
if(waitingThreads != oldNumber)
Progress(true, "%d threads are waiting", waitingThreads);
@@ -323,12 +322,14 @@ class ThreadTest : public ThreadTestBase
}
void SharedSignalAndBroadcastTest (Job *jobs, int numThreads,
- FastOS_Cond *condition,
+ std::mutex *mutex,
+ std::condition_variable *condition,
FastOS_ThreadPool *pool)
{
for(int i=0; i<numThreads; i++)
{
jobs[i].code = WAIT_FOR_CONDITION;
+ jobs[i].mutex = mutex;
jobs[i].condition = condition;
jobs[i].ownThread = pool->NewThread(this,
static_cast<void *>(&jobs[i]));
@@ -338,7 +339,7 @@ class ThreadTest : public ThreadTestBase
}
WaitForXThreadsToHaveWait (jobs, numThreads,
- condition, numThreads);
+ *mutex, numThreads);
// Threads are not guaranteed to have entered sleep yet,
// as this test only tests for result code
@@ -354,15 +355,16 @@ class ThreadTest : public ThreadTestBase
FastOS_ThreadPool pool(128*1024);
Job jobs[numThreads];
- FastOS_Cond condition;
+ std::mutex mutex;
+ std::condition_variable condition;
- SharedSignalAndBroadcastTest(jobs, numThreads, &condition, &pool);
+ SharedSignalAndBroadcastTest(jobs, numThreads, &mutex, &condition, &pool);
for(int i=0; i<numThreads; i++)
{
- condition.Signal();
+ condition.notify_one();
WaitForXThreadsToHaveWait(jobs, numThreads,
- &condition, numThreads-1-i);
+ mutex, numThreads-1-i);
}
Progress(true, "Waiting for threads to finish using pool.Close()...");
@@ -379,12 +381,13 @@ class ThreadTest : public ThreadTestBase
FastOS_ThreadPool pool(128*1024);
Job jobs[numThreads];
- FastOS_Cond condition;
+ std::mutex mutex;
+ std::condition_variable condition;
- SharedSignalAndBroadcastTest(jobs, numThreads, &condition, &pool);
+ SharedSignalAndBroadcastTest(jobs, numThreads, &mutex, &condition, &pool);
- condition.Broadcast();
- WaitForXThreadsToHaveWait(jobs, numThreads, &condition, 0);
+ condition.notify_all();
+ WaitForXThreadsToHaveWait(jobs, numThreads, mutex, 0);
Progress(true, "Waiting for threads to finish using pool.Close()...");
pool.Close();
@@ -401,9 +404,9 @@ class ThreadTest : public ThreadTestBase
FastOS_ThreadPool pool(128*1024);
Job jobs[numThreads];
- FastOS_Mutex slowStartMutex;
+ std::mutex slowStartMutex;
- slowStartMutex.Lock(); // Halt all threads until we want them to run
+ slowStartMutex.lock(); // Halt all threads until we want them to run
for(i=0; i<numThreads; i++) {
jobs[i].code = TEST_ID;
@@ -428,7 +431,7 @@ class ThreadTest : public ThreadTestBase
}
}
- slowStartMutex.Unlock(); // Allow threads to run
+ slowStartMutex.unlock(); // Allow threads to run
Progress(true, "Waiting for threads to finish using pool.Close()...");
pool.Close();
@@ -449,10 +452,12 @@ class ThreadTest : public ThreadTestBase
FastOS_ThreadPool pool(128*1024);
Job job;
- FastOS_Cond condition;
+ std::mutex mutex;
+ std::condition_variable condition;
job.code = WAIT2SEC_AND_SIGNALCOND;
job.result = -1;
+ job.mutex = &mutex;
job.condition = &condition;
job.ownThread = pool.NewThread(this,
static_cast<void *>(&job));
@@ -461,18 +466,17 @@ class ThreadTest : public ThreadTestBase
if(job.ownThread != nullptr)
{
- condition.Lock();
- bool gotCond = condition.TimedWait(500);
+ std::unique_lock<std::mutex> guard(mutex);
+ bool gotCond = condition.wait_for(guard, 500ms) == std::cv_status::no_timeout;
Progress(!gotCond, "We should not get the condition just yet (%s)",
gotCond ? "got it" : "didn't get it");
- gotCond = condition.TimedWait(500);
+ gotCond = condition.wait_for(guard, 500ms) == std::cv_status::no_timeout;
Progress(!gotCond, "We should not get the condition just yet (%s)",
gotCond ? "got it" : "didn't get it");
- gotCond = condition.TimedWait(5000);
+ gotCond = condition.wait_for(guard, 5000ms) == std::cv_status::no_timeout;
Progress(gotCond, "We should have got the condition now (%s)",
gotCond ? "got it" : "didn't get it");
- condition.Unlock();
- }
+ }
Progress(true, "Waiting for threads to finish using pool.Close()...");
pool.Close();
@@ -491,31 +495,22 @@ class ThreadTest : public ThreadTestBase
for(i=0; i<allocCount; i++)
{
- FastOS_Mutex *mtx = new FastOS_Mutex();
- mtx->Lock();
- mtx->Unlock();
+ std::mutex *mtx = new std::mutex;
+ mtx->lock();
+ mtx->unlock();
delete mtx;
if((i % progressIndex) == (progressIndex - 1))
- Progress(true, "Tested %d FastOS_Mutex instances", i + 1);
- }
-
- for(i=0; i<allocCount; i++)
- {
- FastOS_Cond *cond = new FastOS_Cond();
- delete cond;
-
- if((i % progressIndex) == (progressIndex - 1))
- Progress(true, "Tested %d FastOS_Cond instances", i+1);
+ Progress(true, "Tested %d std::mutex instances", i + 1);
}
for(i=0; i<allocCount; i++)
{
- FastOS_BoolCond *cond = new FastOS_BoolCond();
+ std::condition_variable *cond = new std::condition_variable;
delete cond;
if((i % progressIndex) == (progressIndex - 1))
- Progress(true, "Tested %d FastOS_BoolCond instances", i+1);
+ Progress(true, "Tested %d std::condition_variable instances", i+1);
}
PrintSeparator();
@@ -528,13 +523,13 @@ class ThreadTest : public ThreadTestBase
const int allocCount = 150000;
int i;
- FastOS_Mutex **mutexes = new FastOS_Mutex*[allocCount];
+ std::mutex **mutexes = new std::mutex*[allocCount];
FastOS_Time startTime, nowTime;
startTime.SetNow();
for(i=0; i<allocCount; i++)
- mutexes[i] = new FastOS_Mutex();
+ mutexes[i] = new std::mutex;
nowTime.SetNow();
Progress(true, "Allocated %d mutexes at time: %d ms", allocCount,
@@ -543,10 +538,10 @@ class ThreadTest : public ThreadTestBase
for(int e=0; e<4; e++)
{
for(i=0; i<allocCount; i++)
- mutexes[i]->Lock();
+ mutexes[i]->lock();
for(i=0; i<allocCount; i++)
- mutexes[i]->Unlock();
+ mutexes[i]->unlock();
nowTime.SetNow();
Progress(true, "Tested %d mutexes at time: %d ms", allocCount,
diff --git a/fastos/src/tests/typetest.cpp b/fastos/src/tests/typetest.cpp
index 209af305501..503c9a30d24 100644
--- a/fastos/src/tests/typetest.cpp
+++ b/fastos/src/tests/typetest.cpp
@@ -16,11 +16,8 @@ private:
TestHeader("Object Sizes (bytes)");
Progress(true, "FastOS_Application: %d", sizeof(FastOS_Application));
- Progress(true, "FastOS_BoolCond %d", sizeof(FastOS_BoolCond));
- Progress(true, "FastOS_Cond %d", sizeof(FastOS_Cond));
Progress(true, "FastOS_DirectoryScan %d", sizeof(FastOS_DirectoryScan));
Progress(true, "FastOS_File: %d", sizeof(FastOS_File));
- Progress(true, "FastOS_Mutex: %d", sizeof(FastOS_Mutex));
Progress(true, "FastOS_Runnable %d", sizeof(FastOS_Runnable));
Progress(true, "FastOS_ServerSocket %d", sizeof(FastOS_ServerSocket));
Progress(true, "FastOS_Socket: %d", sizeof(FastOS_Socket));
diff --git a/fastos/src/vespa/fastos/CMakeLists.txt b/fastos/src/vespa/fastos/CMakeLists.txt
index 2a0ff2d370a..f98e5b8d97b 100644
--- a/fastos/src/vespa/fastos/CMakeLists.txt
+++ b/fastos/src/vespa/fastos/CMakeLists.txt
@@ -13,11 +13,9 @@ vespa_add_library(fastos_objects OBJECT
time.cpp
timestamp.cpp
unix_app.cpp
- unix_cond.cpp
unix_dynamiclibrary.cpp
unix_file.cpp
unix_ipc.cpp
- unix_mutex.cpp
unix_process.cpp
unix_socket.cpp
unix_thread.cpp
diff --git a/fastos/src/vespa/fastos/app.cpp b/fastos/src/vespa/fastos/app.cpp
index 824d009591f..822683540f7 100644
--- a/fastos/src/vespa/fastos/app.cpp
+++ b/fastos/src/vespa/fastos/app.cpp
@@ -65,7 +65,7 @@ bool FastOS_ApplicationInterface::Init ()
if(errorMsg == nullptr)
{
- _processListMutex = new FastOS_Mutex();
+ _processListMutex = new std::mutex;
_threadPool = new FastOS_ThreadPool(128 * 1024);
rc = true;
}
diff --git a/fastos/src/vespa/fastos/app.h b/fastos/src/vespa/fastos/app.h
index 283db64985c..9560d1ced6a 100644
--- a/fastos/src/vespa/fastos/app.h
+++ b/fastos/src/vespa/fastos/app.h
@@ -15,7 +15,7 @@
class FastOS_ProcessInterface;
class FastOS_ThreadPool;
-#include <vespa/fastos/mutex.h>
+#include <mutex>
/**
* FastOS application wrapper class.
@@ -143,7 +143,7 @@ protected:
FastOS_ThreadPool *_threadPool;
FastOS_ProcessInterface *_processList;
- FastOS_Mutex *_processListMutex;
+ std::mutex *_processListMutex;
bool _disableLeakReporting;
virtual bool PreThreadInit () { return true; }
@@ -248,8 +248,7 @@ public:
void AddChildProcess (FastOS_ProcessInterface *node);
void RemoveChildProcess (FastOS_ProcessInterface *node);
- void ProcessLock () { _processListMutex->Lock(); }
- void ProcessUnlock() { _processListMutex->Unlock(); }
+ std::unique_lock<std::mutex> getProcessGuard() { return std::unique_lock<std::mutex>(*_processListMutex); }
FastOS_ProcessInterface *GetProcessList () { return _processList; }
FastOS_ThreadPool *GetThreadPool ();
diff --git a/fastos/src/vespa/fastos/cond.h b/fastos/src/vespa/fastos/cond.h
deleted file mode 100644
index c9405728223..00000000000
--- a/fastos/src/vespa/fastos/cond.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-//************************************************************************
-/**
- * @file
- * Class definitions for FastOS_CondInterface and FastOS_BoolCond.
- *
- * @author Div, Oivind H. Danielsen
- */
-
-#pragma once
-
-#include "mutex.h"
-
-
-/**
- * This class implements a synchronization mechanism used by threads to wait
- * until a condition expression involving shared data attains a particular state.
- *
- * Condition variables provide a different type of synchronization
- * than locking mechanisms like mutexes. For instance, a mutex is used
- * to cause other threads to wait while the thread holding the mutex
- * executes code in a critical section. In contrast, a condition
- * variable is typically used by a thread to make itself wait until an
- * expression involving shared data attains a particular state.
- */
-class FastOS_CondInterface : public FastOS_Mutex
-{
-public:
- FastOS_CondInterface(void) : FastOS_Mutex() { }
-
- virtual ~FastOS_CondInterface () {}
-
- /**
- * Wait for the condition to be signalled. If the wait takes
- * longer than [milliseconds] ms, the wait is aborted and false
- * is returned.
- * @param milliseconds Max time to wait.
- * @return Boolean success/failure
- */
- virtual bool TimedWait (int milliseconds) = 0;
-
- /**
- * Wait for the condition to be signalled.
- */
- virtual void Wait (void)=0;
-
- /**
- * Send a signal to one thread waiting on the condition (if any).
- */
- virtual void Signal (void)=0;
-
- /**
- * Send a signal to all threads waiting on the condition.
- */
- virtual void Broadcast (void)=0;
-};
-
-#include <vespa/fastos/unix_cond.h>
-typedef FastOS_UNIX_Cond FASTOS_PREFIX(Cond);
-
-/**
- * This class implements a condition variable with a boolean
- * value.
- */
-class FastOS_BoolCond : public FastOS_Cond
-{
- bool _busy;
-
-public:
- /**
- * Constructor. Initially the boolean variable is
- * set to non-busy.
- */
- FastOS_BoolCond(void) : _busy(false) { }
-
- ~FastOS_BoolCond(void) { }
-
- /**
- * If the variable is busy, wait for it to be non-busy,
- * then set the variable to busy. */
- void SetBusy(void)
- {
- Lock();
-
- while (_busy == true)
- Wait();
-
- _busy = true;
- Unlock();
- }
-
- /**
- * If the variable is busy, wait until it is no longer busy.
- * If it was non-busy to begin with, no wait is performed.
- */
- void WaitBusy(void)
- {
- Lock();
-
- while (_busy == true)
- Wait();
-
- Unlock();
- }
-
- /**
- * If the variable is busy, wait until it is no longer busy or a
- * timeout occurs. If it was non-busy to begin with, no wait is
- * performed.
- * @param ms Time to wait
- * @return True=non-busy, false=timeout
- */
- bool TimedWaitBusy(int ms)
- {
- bool success = true;
-
- Lock();
- if (_busy == true) {
- success = TimedWait(ms);
- }
- Unlock();
-
- return success;
- }
-
- /**
- * Return busy status.
- * @return True=busy, false=non-busy
- */
- bool PollBusy (void)
- {
- bool rc;
- Lock();
- rc = _busy;
- Unlock();
- return rc;
- }
-
- /**
- * Set the variable to non-busy, and signal one thread
- * waiting (if there are any).
- * (if any).
- */
- void ClearBusy(void)
- {
- Lock();
- _busy = false;
- Signal();
- Unlock();
- }
-
- /**
- * Set the variable to non-busy, and broadcast to all
- * threads waiting (if there are any).
- */
- void ClearBusyBroadcast(void)
- {
- Lock();
- _busy = false;
- Broadcast();
- Unlock();
- }
-};
-
-
diff --git a/fastos/src/vespa/fastos/mutex.h b/fastos/src/vespa/fastos/mutex.h
deleted file mode 100644
index 530e8d007bc..00000000000
--- a/fastos/src/vespa/fastos/mutex.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-//************************************************************************
-/**
- * @file
- * Class definition for FastOS_Mutex.
- *
- * @author Div, Oivind H. Danielsen
- */
-
-#pragma once
-
-#include "types.h"
-
-/**
- * This class defines a mutual-exclusion object.
- *
- * Facilitates synchronized access to mutual-exclusion zones in the program.
- * Before entering code sections where only a single thread at the time can
- * operate, use @ref Lock(). If another thread is holding the lock at the
- * time, the calling thread will sleep until the current holder of the mutex
- * is through using it.
- *
- * Use @ref Unlock() to release the mutex lock. This will allow other threads
- * to obtain the lock.
- */
-
-class FastOS_MutexInterface
-{
-public:
- /**
- * Destructor
- */
- virtual ~FastOS_MutexInterface () {}
-
- /**
- * Obtain an exclusive lock on the mutex. The result of a recursive lock
- * is currently undefined. The caller should assume this will result
- * in a deadlock situation.
- * A recursive lock occurs when a thread, currently owning the lock,
- * attempts to lock the mutex a second time.
- *
- * Use @ref Unlock() to unlock the mutex when done.
- */
- virtual void Lock ()=0;
-
- /**
- * Try to obtain an exclusive lock on the mutex. If a lock cannot be
- * obtained right away, the method will return false. There will
- * be no blocking/waiting for the mutex lock to be available. If
- * the mutex was locked in the attempt, true is returned.
- * @return Boolean success/failure
- */
- virtual bool TryLock ()=0;
-
- /**
- * Unlock a locked mutex. The result of unlocking a mutex not already
- * locked by the calling thread is undefined.
- */
- virtual void Unlock ()=0;
-};
-
-#include "unix_mutex.h"
-typedef FastOS_UNIX_Mutex FASTOS_PREFIX(Mutex);
-
diff --git a/fastos/src/vespa/fastos/ringbuffer.h b/fastos/src/vespa/fastos/ringbuffer.h
index 53ee003915e..41c0af7385b 100644
--- a/fastos/src/vespa/fastos/ringbuffer.h
+++ b/fastos/src/vespa/fastos/ringbuffer.h
@@ -32,7 +32,7 @@ private:
return (_dataIndex + offset) % _bufferSize;
}
- FastOS_Mutex _mutex;
+ std::mutex _mutex;
public:
void Reset ()
@@ -128,14 +128,6 @@ public:
return _closed;
}
- void Lock ()
- {
- _mutex.Lock();
- }
-
- void Unlock ()
- {
- _mutex.Unlock();
- }
+ std::unique_lock<std::mutex> getGuard() { return std::unique_lock<std::mutex>(_mutex); }
};
diff --git a/fastos/src/vespa/fastos/socketevent.cpp b/fastos/src/vespa/fastos/socketevent.cpp
index a80cb015782..5e542390a53 100644
--- a/fastos/src/vespa/fastos/socketevent.cpp
+++ b/fastos/src/vespa/fastos/socketevent.cpp
@@ -7,7 +7,7 @@
FastOS_SocketEventObjects *FastOS_SocketEventObjects::_objects = nullptr;
-FastOS_Mutex FastOS_SocketEventObjects::_listMutex;
+std::mutex FastOS_SocketEventObjects::_listMutex;
int FastOS_SocketEventObjects::_objectCount = 0;
bool FastOS_SocketEventObjects::_initialized = false;
@@ -55,12 +55,12 @@ bool FastOS_SocketEvent::HandleWakeUp ()
FastOS_SocketEventObjects *FastOS_SocketEventObjects::ObtainObject (FastOS_SocketEvent *event)
{
FastOS_SocketEventObjects *node;
- _listMutex.Lock();
+ std::unique_lock<std::mutex> guard(_listMutex);
if(_objects == nullptr)
{
_objectCount++;
- _listMutex.Unlock();
+ guard.unlock();
node = new FastOS_SocketEventObjects(event);
node->_next = nullptr;
@@ -70,8 +70,6 @@ FastOS_SocketEventObjects *FastOS_SocketEventObjects::ObtainObject (FastOS_Socke
node = _objects;
_objects = node->_next;
node->_next = nullptr;
-
- _listMutex.Unlock();
}
return node;
@@ -81,7 +79,7 @@ void FastOS_SocketEventObjects::ReleaseObject (FastOS_SocketEventObjects *node)
{
if (node != nullptr)
node->ReleasedCleanup();
- _listMutex.Lock();
+ std::lock_guard<std::mutex> guard(_listMutex);
if (_initialized) {
node->_next = _objects;
@@ -90,8 +88,6 @@ void FastOS_SocketEventObjects::ReleaseObject (FastOS_SocketEventObjects *node)
delete node;
_objectCount--;
}
-
- _listMutex.Unlock();
}
@@ -213,15 +209,14 @@ FastOS_SocketEvent::epollFini()
void
FastOS_SocketEventObjects::InitializeClass(void)
{
- _listMutex.Lock();
+ std::lock_guard<std::mutex> guard(_listMutex);
_initialized = true;
- _listMutex.Unlock();
}
void FastOS_SocketEventObjects::ClassCleanup(void)
{
- _listMutex.Lock();
+ std::lock_guard<std::mutex> guard(_listMutex);
_initialized = false;
for (;;)
{
@@ -236,7 +231,6 @@ void FastOS_SocketEventObjects::ClassCleanup(void)
_objectCount--;
}
}
- _listMutex.Unlock();
}
diff --git a/fastos/src/vespa/fastos/socketevent.h b/fastos/src/vespa/fastos/socketevent.h
index 5e457908ace..267f948caf9 100644
--- a/fastos/src/vespa/fastos/socketevent.h
+++ b/fastos/src/vespa/fastos/socketevent.h
@@ -3,11 +3,11 @@
#pragma once
#include "types.h"
-#include "mutex.h"
#include <poll.h>
#include <sys/epoll.h>
#include <vector>
+#include <mutex>
class FastOS_IOEvent
{
@@ -25,7 +25,7 @@ private:
FastOS_SocketEventObjects(const FastOS_SocketEventObjects&);
FastOS_SocketEventObjects& operator=(const FastOS_SocketEventObjects&);
- static FastOS_Mutex _listMutex;
+ static std::mutex _listMutex;
static int _objectCount;
static bool _initialized;
diff --git a/fastos/src/vespa/fastos/thread.cpp b/fastos/src/vespa/fastos/thread.cpp
index 3cd3bb4b85b..5e3400b70e3 100644
--- a/fastos/src/vespa/fastos/thread.cpp
+++ b/fastos/src/vespa/fastos/thread.cpp
@@ -20,6 +20,7 @@ FastOS_ThreadPool::FastOS_ThreadPool(int stackSize, int maxThreads)
_stackSize(stackSize),
_closeCalledFlag(false),
_freeMutex(),
+ _liveMutex(),
_liveCond(),
_freeThreads(nullptr),
_activeThreads(nullptr),
@@ -40,21 +41,20 @@ void FastOS_ThreadPool::ThreadIsAboutToTerminate(FastOS_ThreadInterface *)
{
assert(isClosed());
- _liveCond.Lock();
+ std::lock_guard<std::mutex> guard(_liveMutex);
_numTerminated++;
_numLive--;
- if (_numLive == 0)
- _liveCond.Broadcast();
-
- _liveCond.Unlock();
+ if (_numLive == 0) {
+ _liveCond.notify_all();
+ }
}
// This is a NOP if the thread isn't active.
void FastOS_ThreadPool::FreeThread (FastOS_ThreadInterface *thread)
{
- _freeMutex.Lock();
+ std::lock_guard<std::mutex> guard(_freeMutex);
if(thread->_active) {
LinkOutThread(thread, &_activeThreads);
@@ -65,8 +65,6 @@ void FastOS_ThreadPool::FreeThread (FastOS_ThreadInterface *thread)
LinkInThread(thread, &_freeThreads);
_numFree++;
}
-
- _freeMutex.Unlock();
}
void FastOS_ThreadPool::LinkOutThread (FastOS_ThreadInterface *thread, FastOS_ThreadInterface **listHead)
@@ -110,7 +108,7 @@ FastOS_ThreadInterface *FastOS_ThreadPool::NewThread (FastOS_Runnable *owner, vo
{
FastOS_ThreadInterface *thread=nullptr;
- _freeMutex.Lock();
+ std::unique_lock<std::mutex> freeGuard(_freeMutex);
if (!isClosed()) {
if ((thread = _freeThreads) != nullptr) {
@@ -126,24 +124,21 @@ FastOS_ThreadInterface *FastOS_ThreadPool::NewThread (FastOS_Runnable *owner, vo
fprintf(stderr, "Error: Maximum number of threads (%d)"
" already allocated.\n", _maxThreads);
} else {
- _freeMutex.Unlock();
-
- _liveCond.Lock();
- _numLive++;
- _liveCond.Unlock();
-
+ freeGuard.unlock();
+ {
+ std::lock_guard<std::mutex> liveGuard(_liveMutex);
+ _numLive++;
+ }
thread = FastOS_Thread::CreateThread(this);
if (thread == nullptr) {
- _liveCond.Lock();
+ std::lock_guard<std::mutex> liveGuard(_liveMutex);
_numLive--;
if (_numLive == 0) {
- _liveCond.Broadcast();
+ _liveCond.notify_all();
}
- _liveCond.Unlock();
}
-
- _freeMutex.Lock();
+ freeGuard.lock();
if(thread != nullptr)
ActivateThread(thread);
@@ -151,11 +146,10 @@ FastOS_ThreadInterface *FastOS_ThreadPool::NewThread (FastOS_Runnable *owner, vo
}
}
- _freeMutex.Unlock();
+ freeGuard.unlock();
if(thread != nullptr) {
- _liveCond.Lock();
+ std::lock_guard<std::mutex> liveGuard(_liveMutex);
thread->Dispatch(owner, arg);
- _liveCond.Unlock();
}
return thread;
@@ -166,7 +160,7 @@ void FastOS_ThreadPool::BreakThreads ()
{
FastOS_ThreadInterface *thread;
- _freeMutex.Lock();
+ std::lock_guard<std::mutex> freeGuard(_freeMutex);
// Notice all active threads that they should quit
for(thread=_activeThreads; thread != nullptr; thread=thread->_next) {
@@ -177,26 +171,22 @@ void FastOS_ThreadPool::BreakThreads ()
for(thread=_freeThreads; thread != nullptr; thread=thread->_next) {
thread->SetBreakFlag();
}
-
- _freeMutex.Unlock();
}
void FastOS_ThreadPool::JoinThreads ()
{
- _liveCond.Lock();
-
- while (_numLive > 0)
- _liveCond.Wait();
-
- _liveCond.Unlock();
+ std::unique_lock<std::mutex> liveGuard(_liveMutex);
+ while (_numLive > 0) {
+ _liveCond.wait(liveGuard);
+ }
}
void FastOS_ThreadPool::DeleteThreads ()
{
FastOS_ThreadInterface *thread;
- _freeMutex.Lock();
+ std::lock_guard<std::mutex> freeGuard(_freeMutex);
assert(_numActive == 0);
assert(_numLive == 0);
@@ -209,30 +199,25 @@ void FastOS_ThreadPool::DeleteThreads ()
}
assert(_numFree == 0);
-
- _freeMutex.Unlock();
}
void FastOS_ThreadPool::Close ()
{
- _closeFlagMutex.Lock();
+ std::unique_lock<std::mutex> closeFlagGuard(_closeFlagMutex);
if (!_closeCalledFlag) {
_closeCalledFlag = true;
- _closeFlagMutex.Unlock();
+ closeFlagGuard.unlock();
BreakThreads();
JoinThreads();
DeleteThreads();
- } else {
- _closeFlagMutex.Unlock();
}
}
bool FastOS_ThreadPool::isClosed()
{
- _closeFlagMutex.Lock();
+ std::lock_guard<std::mutex> closeFlagGuard(_closeFlagMutex);
bool closed(_closeCalledFlag);
- _closeFlagMutex.Unlock();
return closed;
}
@@ -262,20 +247,19 @@ void FastOS_ThreadInterface::Hook ()
while(!finished) {
- _dispatched.Lock(); // BEGIN lock
-
+ std::unique_lock<std::mutex> dispatchedGuard(_dispatchedMutex); // BEGIN lock
while (_owner == nullptr && !(finished = _pool->isClosed())) {
- _dispatched.Wait();
+ _dispatchedCond.wait(dispatchedGuard);
}
- _dispatched.Unlock(); // END lock
+ dispatchedGuard.unlock(); // END lock
if(!finished) {
PreEntry();
deleteOnCompletion = _owner->DeleteOnCompletion();
_owner->Run(this, _startArg);
- _dispatched.Lock(); // BEGIN lock
+ dispatchedGuard.lock(); // BEGIN lock
if (deleteOnCompletion) {
delete _owner;
@@ -285,9 +269,13 @@ void FastOS_ThreadInterface::Hook ()
_breakFlag = false;
finished = _pool->isClosed();
- _dispatched.Unlock(); // END lock
+ dispatchedGuard.unlock(); // END lock
- _runningCond.ClearBusyBroadcast();
+ {
+ std::lock_guard<std::mutex> runningGuard(_runningMutex);
+ _runningFlag = false;
+ _runningCond.notify_all();
+ }
_pool->FreeThread(this);
// printf("Thread given back to FastOS_ThreadPool: %p\n", this);
@@ -307,9 +295,15 @@ void FastOS_ThreadInterface::Hook ()
void FastOS_ThreadInterface::Dispatch(FastOS_Runnable *newOwner, void *arg)
{
- _dispatched.Lock();
+ std::lock_guard<std::mutex> dispatchedGuard(_dispatchedMutex);
- _runningCond.SetBusy();
+ {
+ std::unique_lock<std::mutex> runningGuard(_runningMutex);
+ while (_runningFlag) {
+ _runningCond.wait(runningGuard);
+ }
+ _runningFlag = true;
+ }
_owner = newOwner;
_startArg = arg;
@@ -322,18 +316,14 @@ void FastOS_ThreadInterface::Dispatch(FastOS_Runnable *newOwner, void *arg)
// it the safe way we just do that, instead of keeping a unneccessary long
// suppressionslist. It will be long enough anyway.
- _dispatched.Signal();
-
- _dispatched.Unlock();
+ _dispatchedCond.notify_one();
}
void FastOS_ThreadInterface::SetBreakFlag()
{
- _dispatched.Lock();
+ std::lock_guard<std::mutex> dispatchedGuard(_dispatchedMutex);
_breakFlag = true;
-
- _dispatched.Signal();
- _dispatched.Unlock();
+ _dispatchedCond.notify_one();
}
@@ -351,7 +341,10 @@ FastOS_ThreadInterface *FastOS_ThreadInterface::CreateThread(FastOS_ThreadPool *
void FastOS_ThreadInterface::Join ()
{
- _runningCond.WaitBusy();
+ std::unique_lock<std::mutex> runningGuard(_runningMutex);
+ while (_runningFlag) {
+ _runningCond.wait(runningGuard);
+ }
}
diff --git a/fastos/src/vespa/fastos/thread.h b/fastos/src/vespa/fastos/thread.h
index eb43fc6b664..2726efe3cf0 100644
--- a/fastos/src/vespa/fastos/thread.h
+++ b/fastos/src/vespa/fastos/thread.h
@@ -12,8 +12,8 @@
#include "types.h"
-#include "mutex.h"
-#include "cond.h"
+#include <mutex>
+#include <condition_variable>
typedef pthread_t FastOS_ThreadId;
@@ -41,7 +41,7 @@ private:
FastOS_ThreadPool& operator=(const FastOS_ThreadPool&);
int _startedThreadsCount;
- FastOS_Mutex _closeFlagMutex;
+ std::mutex _closeFlagMutex;
/**
* The stack size for threads in this pool.
*/
@@ -49,8 +49,9 @@ private:
bool _closeCalledFlag;
// Always lock in this order
- FastOS_Mutex _freeMutex;
- FastOS_Cond _liveCond;
+ std::mutex _freeMutex;
+ std::mutex _liveMutex;
+ std::condition_variable _liveCond;
/**
* List of free (available) threads.
*/
@@ -232,7 +233,8 @@ protected:
* The thread does not start (call @ref FastOS_Runnable::Run())
* until this event has been triggered.
*/
- FastOS_Cond _dispatched;
+ std::mutex _dispatchedMutex;
+ std::condition_variable _dispatchedCond;
FastOS_ThreadInterface *_next;
FastOS_ThreadInterface *_prev;
@@ -303,7 +305,9 @@ protected:
* Is the thread running? This is used by @ref Join(), to wait for threads
* to finish.
*/
- FastOS_BoolCond _runningCond;
+ std::mutex _runningMutex;
+ std::condition_variable _runningCond;
+ bool _runningFlag;
public:
/**
@@ -324,7 +328,8 @@ public:
* Constructor. Resets internal attributes.
*/
FastOS_ThreadInterface (FastOS_ThreadPool *pool)
- : _dispatched(),
+ : _dispatchedMutex(),
+ _dispatchedCond(),
_next(nullptr),
_prev(nullptr),
_owner(nullptr),
@@ -332,7 +337,9 @@ public:
_startArg(nullptr),
_breakFlag(false),
_active(false),
- _runningCond()
+ _runningMutex(),
+ _runningCond(),
+ _runningFlag(false)
{
}
diff --git a/fastos/src/vespa/fastos/unix_app.cpp b/fastos/src/vespa/fastos/unix_app.cpp
index 7682b2d5b8f..c60035aa5ab 100644
--- a/fastos/src/vespa/fastos/unix_app.cpp
+++ b/fastos/src/vespa/fastos/unix_app.cpp
@@ -162,9 +162,13 @@ void FastOS_UNIX_Application::Cleanup ()
_ipcHelper->Exit();
if (_processStarter != nullptr) {
- if (_processListMutex) ProcessLock();
- _processStarter->Stop();
- if (_processListMutex) ProcessUnlock();
+ {
+ std::unique_lock<std::mutex> guard;
+ if (_processListMutex) {
+ guard = getProcessGuard();
+ }
+ _processStarter->Stop();
+ }
delete _processStarter;
_processStarter = nullptr;
}
diff --git a/fastos/src/vespa/fastos/unix_cond.cpp b/fastos/src/vespa/fastos/unix_cond.cpp
deleted file mode 100644
index 5eb1f5b0218..00000000000
--- a/fastos/src/vespa/fastos/unix_cond.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "cond.h"
-#include <sys/time.h>
-#include <cstdint>
-
-FastOS_UNIX_Cond::FastOS_UNIX_Cond(void)
- : FastOS_CondInterface(),
- _cond()
-{
- pthread_cond_init(&_cond, nullptr);
-}
-
-FastOS_UNIX_Cond::~FastOS_UNIX_Cond(void)
-{
- pthread_cond_destroy(&_cond);
-}
-
-void
-FastOS_UNIX_Cond::Wait(void)
-{
- pthread_cond_wait(&_cond, &_mutex);
-}
-
-bool
-FastOS_UNIX_Cond::TimedWait(int milliseconds)
-{
-
- struct timeval currentTime;
- struct timespec absTime;
- int error;
-
- gettimeofday(&currentTime, nullptr);
-
- int64_t ns = (static_cast<int64_t>(currentTime.tv_sec) *
- static_cast<int64_t>(1000 * 1000 * 1000) +
- static_cast<int64_t>(currentTime.tv_usec) *
- static_cast<int64_t>(1000) +
- static_cast<int64_t>(milliseconds) *
- static_cast<int64_t>(1000 * 1000));
-
- absTime.tv_sec = static_cast<int>
- (ns / static_cast<int64_t>(1000 * 1000 * 1000));
- absTime.tv_nsec = static_cast<int>
- (ns % static_cast<int64_t>(1000 * 1000 * 1000));
-
- error = pthread_cond_timedwait(&_cond, &_mutex, &absTime);
- return error == 0;
-}
diff --git a/fastos/src/vespa/fastos/unix_cond.h b/fastos/src/vespa/fastos/unix_cond.h
deleted file mode 100644
index 7367d812959..00000000000
--- a/fastos/src/vespa/fastos/unix_cond.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-//************************************************************************
-/**
- * Class definition and implementation for FastOS_UNIX_Cond.
- *
- * @author Div, Oivind H. Danielsen
- */
-
-#pragma once
-
-#include <vespa/fastos/cond.h>
-
-
-class FastOS_UNIX_Cond : public FastOS_CondInterface
-{
-private:
- FastOS_UNIX_Cond(const FastOS_UNIX_Cond &);
- FastOS_UNIX_Cond& operator=(const FastOS_UNIX_Cond &);
-
- pthread_cond_t _cond;
-
-public:
- FastOS_UNIX_Cond ();
-
- ~FastOS_UNIX_Cond();
-
- void Wait() override;
-
- bool TimedWait(int milliseconds) override;
-
- void Signal() override
- {
- pthread_cond_signal(&_cond);
- }
-
- void Broadcast() override
- {
- pthread_cond_broadcast(&_cond);
- }
-};
-
-
diff --git a/fastos/src/vespa/fastos/unix_ipc.cpp b/fastos/src/vespa/fastos/unix_ipc.cpp
index 695d395674f..79fbe3ee076 100644
--- a/fastos/src/vespa/fastos/unix_ipc.cpp
+++ b/fastos/src/vespa/fastos/unix_ipc.cpp
@@ -5,6 +5,8 @@
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
+#include <memory>
+#include <future>
FastOS_UNIX_IPCHelper::
FastOS_UNIX_IPCHelper (FastOS_ApplicationInterface *app, int descriptor)
@@ -55,7 +57,7 @@ DoWrite(FastOS_UNIX_Process::DescriptorHandle &desc)
bool rc = true;
FastOS_RingBuffer *buffer = desc._writeBuffer.get();
- buffer->Lock();
+ auto bufferGuard = buffer->getGuard();
int writeBytes = buffer->GetReadSpace();
if(writeBytes > 0)
{
@@ -78,8 +80,6 @@ DoWrite(FastOS_UNIX_Process::DescriptorHandle &desc)
else if(bytesWritten == 0)
desc.CloseHandle();
}
- buffer->Unlock();
-
return rc;
}
@@ -90,7 +90,7 @@ DoRead (FastOS_UNIX_Process::DescriptorHandle &desc)
FastOS_RingBuffer *buffer = desc._readBuffer.get();
- buffer->Lock();
+ auto bufferGuard = buffer->getGuard();
int readBytes = buffer->GetWriteSpace();
if(readBytes > 0) {
int bytesRead;
@@ -108,7 +108,6 @@ DoRead (FastOS_UNIX_Process::DescriptorHandle &desc)
desc.CloseHandle();
}
}
- buffer->Unlock();
return rc;
}
@@ -430,8 +429,7 @@ RemoveClosingProcesses(void)
if(!stillBusy)
{
- if(xproc->_closing != nullptr)
- {
+ if (xproc->_closing) {
// We already have the process lock at this point,
// so modifying the list is safe.
_app->RemoveChildProcess(node);
@@ -450,7 +448,8 @@ RemoveClosingProcesses(void)
}
// The process destructor can now proceed
- xproc->_closing->ClearBusy();
+ auto closingPromise(std::move(xproc->_closing));
+ closingPromise->set_value();
}
}
}
@@ -474,31 +473,32 @@ Run(FastOS_ThreadInterface *thisThread, void *arg)
for(;;)
{
// Deliver messages to from child processes and parent.
- _app->ProcessLock();
- for(node = _app->GetProcessList(); node != nullptr; node = node->_next)
{
- FastOS_UNIX_Process *xproc = static_cast<FastOS_UNIX_Process *>(node);
- FastOS_UNIX_Process::DescriptorHandle &desc =
- xproc->GetDescriptorHandle(FastOS_UNIX_Process::TYPE_IPC);
- DeliverMessages(desc._readBuffer.get());
- PipeData(xproc, FastOS_UNIX_Process::TYPE_STDOUT);
- PipeData(xproc, FastOS_UNIX_Process::TYPE_STDERR);
- }
- DeliverMessages(_appParentIPCDescriptor._readBuffer.get());
-
- // Setup file descriptor sets for the next select() call
- BuildPollChecks();
-
- // Close and signal closing processes
- RemoveClosingProcesses();
+ auto guard = _app->getProcessGuard();
+ for(node = _app->GetProcessList(); node != nullptr; node = node->_next)
+ {
+ FastOS_UNIX_Process *xproc = static_cast<FastOS_UNIX_Process *>(node);
+ FastOS_UNIX_Process::DescriptorHandle &desc =
+ xproc->GetDescriptorHandle(FastOS_UNIX_Process::TYPE_IPC);
+ DeliverMessages(desc._readBuffer.get());
+ PipeData(xproc, FastOS_UNIX_Process::TYPE_STDOUT);
+ PipeData(xproc, FastOS_UNIX_Process::TYPE_STDERR);
+ }
+ DeliverMessages(_appParentIPCDescriptor._readBuffer.get());
- BuildPollArray(&fds, &nfds, &allocnfds);
+ // Setup file descriptor sets for the next select() call
+ BuildPollChecks();
- _app->ProcessUnlock();
+ // Close and signal closing processes
+ RemoveClosingProcesses();
- _lock.Lock();
- bool exitFlag(_exitFlag);
- _lock.Unlock();
+ BuildPollArray(&fds, &nfds, &allocnfds);
+ }
+ bool exitFlag = false;
+ {
+ std::lock_guard<std::mutex> guard(_lock);
+ exitFlag = _exitFlag;
+ }
if (exitFlag)
{
if (_appParentIPCDescriptor._fd != -1)
@@ -546,11 +546,13 @@ Run(FastOS_ThreadInterface *thisThread, void *arg)
break;
}
- _app->ProcessLock();
- bool woken = SavePollArray(fds, nfds);
- // Do actual IO (based on file descriptor sets and buffer contents)
- PerformAsyncIO();
- _app->ProcessUnlock();
+ bool woken = false;
+ {
+ auto guard = _app->getProcessGuard();
+ woken = SavePollArray(fds, nfds);
+ // Do actual IO (based on file descriptor sets and buffer contents)
+ PerformAsyncIO();
+ }
PerformAsyncIPCIO();
// Did someone want to wake us up from the poll() call?
@@ -584,7 +586,7 @@ SendMessage (FastOS_UNIX_Process *xproc, const void *buffer,
ipcBuffer = desc._writeBuffer.get();
if(ipcBuffer != nullptr) {
- ipcBuffer->Lock();
+ auto ipcBufferGuard = ipcBuffer->getGuard();
if(ipcBuffer->GetWriteSpace() >= int((length + sizeof(int)))) {
memcpy(ipcBuffer->GetWritePtr(), &length, sizeof(int));
@@ -595,7 +597,6 @@ SendMessage (FastOS_UNIX_Process *xproc, const void *buffer,
NotifyProcessListChange();
rc = true;
}
- ipcBuffer->Unlock();
}
return rc;
}
@@ -611,10 +612,9 @@ void FastOS_UNIX_IPCHelper::NotifyProcessListChange ()
void FastOS_UNIX_IPCHelper::Exit ()
{
- _lock.Lock();
+ std::lock_guard<std::mutex> guard(_lock);
_exitFlag = true;
NotifyProcessListChange();
- _lock.Unlock();
}
void FastOS_UNIX_IPCHelper::AddProcess (FastOS_UNIX_Process *xproc)
@@ -639,16 +639,11 @@ void FastOS_UNIX_IPCHelper::AddProcess (FastOS_UNIX_Process *xproc)
void FastOS_UNIX_IPCHelper::RemoveProcess (FastOS_UNIX_Process *xproc)
{
- (void)xproc;
-
- FastOS_BoolCond closeWait;
-
- closeWait.SetBusy();
- xproc->_closing = &closeWait;
-
+ auto closePromise = std::make_unique<std::promise<void>>();
+ auto closeFuture = closePromise->get_future();
+ xproc->_closing = std::move(closePromise);
NotifyProcessListChange();
-
- closeWait.WaitBusy();
+ closeFuture.wait();
}
void FastOS_UNIX_IPCHelper::DeliverMessages (FastOS_RingBuffer *buffer)
@@ -656,7 +651,7 @@ void FastOS_UNIX_IPCHelper::DeliverMessages (FastOS_RingBuffer *buffer)
if(buffer == nullptr)
return;
- buffer->Lock();
+ auto bufferGuard = buffer->getGuard();
unsigned int readSpace;
while((readSpace = buffer->GetReadSpace()) > sizeof(int))
@@ -673,8 +668,6 @@ void FastOS_UNIX_IPCHelper::DeliverMessages (FastOS_RingBuffer *buffer)
else
break;
}
-
- buffer->Unlock();
}
void FastOS_UNIX_IPCHelper::
@@ -690,7 +683,7 @@ PipeData (FastOS_UNIX_Process *process,
if(listener == nullptr)
return;
- buffer->Lock();
+ auto bufferGuard = buffer->getGuard();
unsigned int readSpace;
while((readSpace = buffer->GetReadSpace()) > 0) {
@@ -700,6 +693,4 @@ PipeData (FastOS_UNIX_Process *process,
if(buffer->GetCloseFlag())
process->CloseListener(type);
-
- buffer->Unlock();
}
diff --git a/fastos/src/vespa/fastos/unix_ipc.h b/fastos/src/vespa/fastos/unix_ipc.h
index 35e77e11cb2..218096e2145 100644
--- a/fastos/src/vespa/fastos/unix_ipc.h
+++ b/fastos/src/vespa/fastos/unix_ipc.h
@@ -13,7 +13,7 @@ private:
FastOS_UNIX_IPCHelper& operator=(const FastOS_UNIX_IPCHelper&);
protected:
- FastOS_Mutex _lock;
+ std::mutex _lock;
volatile bool _exitFlag;
FastOS_ApplicationInterface *_app;
diff --git a/fastos/src/vespa/fastos/unix_mutex.cpp b/fastos/src/vespa/fastos/unix_mutex.cpp
deleted file mode 100644
index 535a39ce592..00000000000
--- a/fastos/src/vespa/fastos/unix_mutex.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "mutex.h"
-#include <cassert>
-
-FastOS_UNIX_Mutex::FastOS_UNIX_Mutex(void)
- : FastOS_MutexInterface(),
- _mutex()
-{
- int error = pthread_mutex_init(&_mutex, nullptr);
- assert(error == 0);
- (void) error;
-}
-
-FastOS_UNIX_Mutex::~FastOS_UNIX_Mutex(void)
-{
- pthread_mutex_destroy(&_mutex);
-}
diff --git a/fastos/src/vespa/fastos/unix_mutex.h b/fastos/src/vespa/fastos/unix_mutex.h
deleted file mode 100644
index 30150bc1590..00000000000
--- a/fastos/src/vespa/fastos/unix_mutex.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-/**
-******************************************************************************
-* @author Oivind H. Danielsen
-* @date Creation date: 2000-02-02
-* @file
-* Class definition and implementation for FastOS_UNIX_Mutex
-*****************************************************************************/
-
-
-
-#pragma once
-
-
-#include "mutex.h"
-#include <pthread.h>
-
-class FastOS_UNIX_Mutex : public FastOS_MutexInterface
-{
-private:
- FastOS_UNIX_Mutex(const FastOS_UNIX_Mutex &other);
- FastOS_UNIX_Mutex & operator = (const FastOS_UNIX_Mutex &other);
-protected:
- pthread_mutex_t _mutex;
-
-public:
- FastOS_UNIX_Mutex();
-
- ~FastOS_UNIX_Mutex();
-
- bool TryLock () override {
- return pthread_mutex_trylock(&_mutex) == 0;
- }
-
- void Lock() override {
- pthread_mutex_lock(&_mutex);
- }
-
- void Unlock() override {
- pthread_mutex_unlock(&_mutex);
- }
-};
-
-
diff --git a/fastos/src/vespa/fastos/unix_process.cpp b/fastos/src/vespa/fastos/unix_process.cpp
index df32cb935ff..80ad0605f78 100644
--- a/fastos/src/vespa/fastos/unix_process.cpp
+++ b/fastos/src/vespa/fastos/unix_process.cpp
@@ -805,9 +805,10 @@ FastOS_UNIX_Process (const char *cmdLine, bool pipeStdin,
if (stderrListener != nullptr)
_descriptor[TYPE_STDERR]._readBuffer.reset(new FastOS_RingBuffer(bufferSize));
- _app->ProcessLock();
- _app->AddChildProcess(this);
- _app->ProcessUnlock();
+ {
+ auto guard = _app->getProcessGuard();
+ _app->AddChildProcess(this);
+ }
// App::AddToIPCComm() is performed when the process is started
}
@@ -825,9 +826,8 @@ FastOS_UNIX_Process::~FastOS_UNIX_Process ()
static_cast<FastOS_UNIX_Application *>(_app)->RemoveFromIPCComm(this);
} else {
// No IPC descriptor, do it ourselves
- _app->ProcessLock();
+ auto guard = _app->getProcessGuard();
_app->RemoveChildProcess(this);
- _app->ProcessUnlock();
}
for(int i=0; i<int(TYPE_COUNT); i++) {
@@ -897,7 +897,7 @@ bool FastOS_UNIX_Process::Signal(int sig)
bool rc = false;
pid_t pid;
- _app->ProcessLock();
+ auto guard = _app->getProcessGuard();
pid = GetProcessId();
if (pid == 0) {
/* Do nothing */
@@ -908,7 +908,6 @@ bool FastOS_UNIX_Process::Signal(int sig)
_killed = true;
rc = true;
}
- _app->ProcessUnlock();
return rc;
}
@@ -1722,7 +1721,7 @@ CreateProcess (FastOS_UNIX_Process *process,
const char *cmdLine = process->GetCommandLine();
- process->_app->ProcessLock();
+ auto guard = _app->getProcessGuard();
if (process->GetDirectChild()) {
_hasDirectChildren = true;
@@ -1770,7 +1769,7 @@ CreateProcess (FastOS_UNIX_Process *process,
"Forkandexec %s failed\n",
cmdLine);
}
- process->_app->ProcessUnlock();
+ guard.unlock();
delete rprocess;
FreeEnvironmentVariables(env);
return rc;
@@ -1847,8 +1846,6 @@ CreateProcess (FastOS_UNIX_Process *process,
}
}
}
- process->_app->ProcessUnlock();
-
return rc;
}
@@ -1926,13 +1923,13 @@ FastOS_UNIX_ProcessStarter::Wait(FastOS_UNIX_Process *process,
*pollStillRunning = true;
for (;;) {
- process->_app->ProcessLock();
-
- if (_hasDirectChildren) PollReapDirectChildren();
+ {
+ auto guard = process->_app->getProcessGuard();
- if (_hasProxiedChildren) PollReapProxiedChildren();
+ if (_hasDirectChildren) PollReapDirectChildren();
- process->_app->ProcessUnlock();
+ if (_hasProxiedChildren) PollReapProxiedChildren();
+ }
if (process->GetDeathFlag()) {
if (pollStillRunning != nullptr)
@@ -1971,16 +1968,14 @@ bool FastOS_UNIX_ProcessStarter::Detach(FastOS_UNIX_Process *process)
bool rc = true;
pid_t pid;
- process->_app->ProcessLock();
+ auto guard = process->_app->getProcessGuard();
pid = process->GetProcessId();
if (pid == 0) {
- process->_app->ProcessUnlock();
return false; // Cannot detach nonstarted process.
}
if (process->GetDeathFlag()) {
- process->_app->ProcessUnlock();
return true;
}
@@ -2004,7 +1999,6 @@ bool FastOS_UNIX_ProcessStarter::Detach(FastOS_UNIX_Process *process)
ReadBytes(_mainSocket, &returnCode, sizeof(int));
process->DeathNotification(returnCode);
}
- process->_app->ProcessUnlock();
return rc;
}
@@ -2044,4 +2038,4 @@ FastOS_UNIX_Process::DescriptorHandle::CloseHandleDirectChild()
close(_fd);
_fd = -1;
}
-} \ No newline at end of file
+}
diff --git a/fastos/src/vespa/fastos/unix_process.h b/fastos/src/vespa/fastos/unix_process.h
index 16614deb1a2..bff5a1d276e 100644
--- a/fastos/src/vespa/fastos/unix_process.h
+++ b/fastos/src/vespa/fastos/unix_process.h
@@ -12,8 +12,8 @@
#include "app.h"
#include <string>
#include <memory>
+#include <future>
-class FastOS_BoolCond;
class FastOS_UNIX_RealProcess;
class FastOS_RingBuffer;
@@ -78,7 +78,7 @@ public:
{
TYPE_READCOUNT = 3
};
- FastOS_BoolCond *_closing;
+ std::unique_ptr<std::promise<void>> _closing;
FastOS_ProcessRedirectListener *GetListener (DescriptorType type)
{
if(type == TYPE_STDOUT)
diff --git a/fnet/src/vespa/fnet/fnet.h b/fnet/src/vespa/fnet/fnet.h
index 7b8404376d7..5a3a8b28942 100644
--- a/fnet/src/vespa/fnet/fnet.h
+++ b/fnet/src/vespa/fnet/fnet.h
@@ -3,8 +3,6 @@
#pragma once
#include <vespa/vespalib/component/vtag.h>
-#include <vespa/fastos/mutex.h>
-#include <vespa/fastos/cond.h>
// DEPRECATED