64,647
社区成员
发帖
与我相关
我的任务
分享
#ifndef SYNCHRONIZED_LIST_H
#define SYNCHRONIZED_LIST_H
#include <iostream>
#include <vector>
#include <mutex>
using namespace std;
template <class T>
class SyncList {
public:
SyncList() :low_mark(0), high_mark(1), hasShutDown(false) {};
SyncList(size_t l, size_t h) :
low_mark(l), high_mark(h), hasShutDown(false) {
if (low_mark < 0) low_mark = 0;
if (high_mark <= 0) high_mark = 1;
};
SyncList(const SyncList&);
void push_back(const T&);
void pop_back(T&);
void push_front(const T&);
void pop_front(T&);
bool empty() const;
void shut_down();
void reset();
private:
bool hasShutDown;
size_t low_mark;
size_t high_mark;
mutable mutex mtx;
condition_variable cond;
vector<T> vec;
};
template <class T>
SyncList<T>::SyncList(const SyncList<T>& other) {
lock(mtx, other.mtx);
lock_guard<mutex> lck1(mtx, adopt_lock);
lock_guard<mutex> lck2(other.mtx, adopt_lock);
low_mark = other.low_mark;
high_mark = other.high_mark;
vec = other.vec;
}
template <class T>
void SyncList<T>::push_back(const T& value)
{
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() <= high_mark;
});
cout << "Push back " << value << endl;
vec.push_back(value);
cond.notify_one();
}
template <class T>
void SyncList<T>::pop_back(T& value)
{
if (!hasShutDown) {
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() >= low_mark;
});
// lck.unlock();
value = vec.back();
vec.pop_back();
cout << "Pop back " << value << " Size of list is: " << vec.size() << " is shut_down: " << (hasShutDown?"Yes":"No") << endl;
cond.notify_one();
}
}
template <class T>
void SyncList<T>::push_front(const T& value)
{
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() <= high_mark;
});
cout << "Push front " << value << endl;
vec.insert(vec.begin(), value);
cond.notify_one();
}
template <class T>
void SyncList<T>::pop_front(T& value)
{
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] {
return vec.size() >= low_mark;
});
// lck.unlock();
value = vec.front();
cout << "Pop front " << value << endl;
vec.erase(vec.begin());
cond.notify_one();
}
template <class T>
bool SyncList<T>::empty() const {
lock_guard<mutex> lck(mtx);
return vec.empty();
}
template <class T>
void SyncList<T>::shut_down() {
//{
lock_guard<mutex> lck(mtx);
hasShutDown = true;
cond.notify_all();
//}
// hasShutDown = false;
}
template <class T>
void SyncList<T>::reset() {
lock_guard<mutex> lck(mtx);
hasShutDown = false;
}
#endif
#ifndef ACTIVE_OBJECT_H
#define ACTIVE_OBJECT_H
#include "synchronized_list.h"
using namespace std;
template <class T>
class ActiveObj {
public:
ActiveObj() :list(SyncList<T>(1, 500)), isActive(false) {};
void enque(const T&);
void active();
void deactive();
private:
SyncList<T> list;
void run_service();
bool isActive;
};
template <class T>
void ActiveObj<T>::enque(const T& value) {
list.push_front(value);
}
template <class T>
void ActiveObj<T>::active() {
if (!isActive) {
isActive = true;
list.reset();
thread(&ActiveObj<T>::run_service, this).detach();
// thread(&ActiveObj<T>::run_service, this).join();
// cout << "Thread joined" << endl;
}
}
template <class T>
void ActiveObj<T>::deactive() {
isActive = false;
list.shut_down();
}
template <class T>
void ActiveObj<T>::run_service() {
T value;
while (isActive) {
if (list.empty()) {
this_thread::yield();
}
else {
cout << "I'm running" << endl;
list.pop_back(value);
}
}
}
#endif
#include <iostream>
#include <mutex>
#include <stdlib.h>
#include <thread>
#include <time.h>
#include <random>
#include <chrono>
#include "active_object.h"
int numbers[500];
template <class T>
void pushFifty(ActiveObj<T>& obj) {
for (int i = 0; i < 500; i++) {
obj.enque(numbers[i]);
}
}
int main(int argc, char* argv[])
{
ActiveObj<int> obj;
srand(time(NULL));
for (int i = 0; i < 500; i++) {
numbers[i] = rand() % 500 + 1;
cout << numbers[i] << " ";
}
cout << endl;
//*
cout << "Starting pushing" << endl;
pushFifty(obj);
cout << "Active now" << endl;
obj.active();
cout << "Sleep 3 seconds" << endl;
this_thread::sleep_for(chrono::seconds(3));
cout << "Pushing again" << endl;
pushFifty(obj);
cout << "Starting Deactiving" << endl;
obj.deactive();
cout << "Active again" << endl;
obj.active();
cout << endl;
//*/
return EXIT_SUCCESS;
}