Example: producer consumer and resource management
Hüseyin Tuğrul BÜYÜKIŞIK edited this page Feb 12, 2021
·
3 revisions
Here, resource management independency between "supply depot" and "virtual array" is shown with a "producer-consumer" example:
#include "GraphicsCardSupplyDepot.h"
#include "VirtualMultiArray.h"
#include "PcieBandwidthBenchmarker.h"
#include <thread>
#include <mutex>
const int MSG = 400;
std::mutex m;
template<typename T>
std::thread producer(VirtualMultiArray<T> arr, std::vector<T> & consumers)
{
// pass-by-value test
std::thread t([&,arr,consumers](){
{
std::unique_lock<std::mutex> lock(m);
std::cout<<"Producer starting production....."<<std::endl;
}
for(auto & c:consumers)
{
{
std::unique_lock<std::mutex> lock(m);
std::cout<<" id: "<<c<<std::endl;
}
arr.set(c,MSG);
}
std::unique_lock<std::mutex> lock(m);
std::cout<<"producer produced things"<<std::endl;
});
return t;
}
template<typename T>
std::thread consumer(VirtualMultiArray<T> arr, const int idx)
{
// pass-by-value test
std::thread t([&,arr, idx](){
while(MSG!=arr.get(idx)){
std::this_thread::yield();
}
std::unique_lock<std::mutex> lock(m);
std::cout<<std::string("consumer-")+std::to_string(idx)+ std::string(" consumed something")<<std::endl;
});
return t;
}
struct Resources
{
// supply depot is not needed to out-live virtual array. Once VirtualMultiArray is created, supply depot can be destructed freely
// but needs to be constructed first
GraphicsCardSupplyDepot d;
// 1 unique gpu channel per element to evade dead-lock between producer - consumer
VirtualMultiArray<int> channels=VirtualMultiArray<int>(10,d.requestGpus(),1,1,{10,0,0,0,0,0},VirtualMultiArray<int>::MemMult::UseDefault,false);
Resources(){}
};
int main(int argC, char ** argV)
{
VirtualMultiArray<int> channels;
{
Resources r;
// out-of-raii-scope testing
channels = r.channels;
}// here, "resources" is gone, but channels are still usable since virtual array's internal data is shared on a unique raw pointer
// now, "channels" own/retain same opencl resource management from r.channels
std::thread t[11];
std::vector<int> idx;
for(int i=0;i<10;i++)
{
idx.push_back(i);
t[i]=consumer(channels,i); // 10 consumers own the same channels (pass-by-value) through shared_ptr-managed bits
}
t[10]=producer(channels,idx); // yet another instance of virtual array that point to same opencl environment
for(int i=0;i<11;i++)
{
t[i].join();
}
return 0;
}