Reputation: 585
Hi I have an application that uses one thread to copy buffer from *src
to *dst
but I want to have the thread started at the beginning of the program. When I want to use the thread I want to pass *src
, *dst
and size
to the thread so that it can start copying the buffer. How do I achieve this ? Because when I start a thread I pass the values as I instantiate the object, ThreadX
when creating a thread.
Thread^ t0 = gcnew Thread(gcnew ThreadStart(gcnew ThreadX(output, input, size), &ThreadX::ThreadEntryPoint));
To summarize I want to do this way:
The sample code is shown below.
Thanks!
#include "stdafx.h"
#include <iostream>
#if 1
using namespace System;
using namespace System::Diagnostics;
using namespace System::Runtime::InteropServices;
using namespace System::Threading;
public ref class ThreadX
{
unsigned short* destination;
unsigned short* source;
unsigned int num;
public:
ThreadX(unsigned short* dstPtr, unsigned short* srcPtr, unsigned int size)
{
destination = dstPtr;
source = srcPtr;
num = size;
}
void ThreadEntryPoint()
{
memcpy(destination, source, sizeof(unsigned short)*num);
}
};
int main()
{
int size = 5056 * 2960 * 10; //iris 15 size
unsigned short* input; //16bit
unsigned short* output;
Stopwatch^ sw = gcnew Stopwatch();
input = new unsigned short[size];
output = new unsigned short[size];
//elapsed time for each test
int sw0;
int sw1;
int sw2;
int sw3;
//initialize input
for (int i = 0; i < size; i++) { input[i] = i % 0xffff; }
//initialize output
for (int i = 0; i < size; i++) { output[i] = 0; }
// TEST 1 //////////////////////////////////////////////////////////////////////
for (int i = 0; i < size; i++) { output[i] = 0; }
//-----------------------------------------------------------------------
Thread^ t0 = gcnew Thread(gcnew ThreadStart(gcnew ThreadX(output, input, size), &ThreadX::ThreadEntryPoint));
t0->Name = "t1";
t0->Start();
t0->Join();
//-----------------------------------------------------------------------
return 0
}
Upvotes: 0
Views: 814
Reputation: 336
Basically, you need some basic building blocks for solving this problem (I am assuming you want to perform this copy operation just once. We can easily extend the solution if you have a constant stream of inputs):
1) Shared memory - For exchanging control information. In this case, it would be source buffer pointer, destination buffer pointer and size (from main thread to worker thread). You would also want some datastructure (lets begin with a simple boolean flag) to share information in the reverse direction (from worker thread to main thread), when the work is done.
2) Conditional variable - To send signal from main thread to worker thread, and in reverse direction. So, you need 2 different conditional variables.
3) A synchronization primitive like a mutex to protect the shared memory (Since they would be simultaneously accessed by both threads)
Given these building blocks, the pseudo code of your program will look like this:
struct Control {
void* src, *dest;
int num_of_bytes = -1;
bool isDone = false;
conditional_var inputReceived;
conditional_var copyDone;
mutex m;
};
void childThread() {
m.lock();
while (num_of_bytes == -1) {
inputReceived.wait(m); // wait till you receive input.
}
// Input received. Make sure you set src and dest pointers, before setting num_of_bytes
mempcy(dest, src, num_of_bytes);
isDone = true; // mark work completion.
copyDone.notify(); // notify the main thread of work completion.
m.unlock();
}
void mainThread()
{
// Create worker thread at start;
thread_t thread = pthread_create(&childThread);
// Do other stuff...
//
//
// Input parameters received. Set control information, and notify the
// workerthread.
mutex.lock();
src = input.src;
dest = input.dest;
num_of_bytes = input.num_of_bytes;
inputReceived.notify(); // wake up worker thread.
while (!isDone) { // Wait for copy to be over.
copyDone.wait();
}
m.unlock(); // unlock the mutex.
thread.join(); // wait for thread to join. If the thread has already ended before we execute thread join, it will return immediately.
}
If you want to extend this solution to handle a stream of inputs, we can use 2 queues for requests and responses, with each element of the queue being input and output parameters.
Upvotes: 1
Reputation: 27864
Don't suspend the thread. That's bad design, and is highly likely to cause you problems down the road.
Instead, think of it like this: Have the thread block waiting for information on what it should do. When it gets that information, it should unblock, do the work, then block again waiting for the next thing.
A quick search for "C# blocking collection" reveals the BlockingCollection<T>
class, and this guide to cancelling one of the blocking operations. Make it so that you activate the CancellationToken when it's time for your thread to exit, and have the thread sit waiting at the blocking operation when it's not doing work.
Upvotes: 0