How to use uv_accept in multithread environment? - libuv

I found that both parameters(server and handle) of uv_accept are required in same uv_loop. but I want to make new connection handle in a sub thread which has its own uv_loop. What should I do?

You will need to run an event loop on each worker thread and have a uv_pipe_t to communicate between the master and the workers. Then on the acceptor thread (the one which calls uv_accept) you can send the accepted handle to a worker over a pipe, using uv_write2.

Related

blocking Inter task communication in RTOS

I'm writing a module which contains a task with the highest priority and it should be in blocking until it receives a message from an other task the start doing its duty as a highest priority task. It uses mailbox mechanism for signaling .
My problem is
I want the task -which send a signal to higher task- gets back message in blocking mode
Here is my question
should I post through mailbox 1 and then fetch from mailbox 2 or there is a better solution?
I use "FreeRTOS" if it helps
EDIT
I think I described the problem very bad
I mean do I need 2 mailbox in order to communicate between task to task or ISR to task or I can use just one mailbox with other implementation!!??
For your edited question:
You have to use two message queues. One for each task otherwise you won't be able to wait correctly.
So for your blocking message transfer, the code looks like this:
High priority task:
while(-1){
xQueueReceive(high_prio_queue, &msg, portMAX_DELAY);
[your complex code]
xQueueSend(low_prio_queue, &return_msg, timeout);
}
Low priority task:
xQueueSend(high_prio_queue, &msg, timeout);
//will only wait if your high priority task gets blocked before sending
xQueueReceive(low_prio_queue, &return_msg, portMAX_DELAY);
From ISR:
xQueueSendFromISR(high_prio_queue, &msg, &unblocked);
It is very simple. For example queues used and the freeRTOS.
The task waits for the queue. It is in the blocked state
while(1)
{
xQueueReceive(queue, &object, portMAX_DELAY);
....
another task send the data to the queue.
xQueueSend(queue, &object, timeout);
When the data is received the task is given the control. Then it checks if anything is in the queue. If not it waits in blocked state.

.threads and parallelProcessing in camel

Route :
ExecutorService executorService = new ThreadPoolBuilder(context).poolSize(10).maxQueueSize(100).build("myCustom-Thread");
from("direct:myROute")
.aggregate(myAggregationStrategy).constant(true)
.threads().executorService(executorService)
//.parallelProcessing().executorService(executorService)
.process(myProcessor)
.end();
I am trying to process the processor logic to run in multithreaded, but in the available options from camel I am getting confused on below behavior
Using .threads with executorService
though it is getting me 10 threads as per the executorService configuration, but all threads are running one by one. which gives me the same behavior as of single thread and also degrading the performance
Using .parallelProcessing with executorService
all threads(10) are running in parallel, but caller thread(main thread of route) get called while threads(parallel processing threads) are still doing their job.
which is not correct.
how can I handle this scenario, in which I can call the caller once all threads are complete their job?

Design of multi-threaded server in c

When trying to implement a simple echo server with concurrent support on linux.
Following approaches are used:
Use pthread functions to create a pool of thread, and maintained in a linked list. It's created on process start, and destroy on process termination.
Main thread will accept request, and use a POSIX message queue to store accepted socket file descriptor.
Threads in pool loop to read from message queue, and handle request it gets, when there is no request, it will block.
The program seems working now.
The questions are:
Is it suitable to use message queue in the middle, is it efficient enough?
What is the general approach to accomplish a thread tool that needs to handle concurrent request from multiple clients?
If it's not proper to make threads in pool loop & block to retrieve msg from message queue, then how to deliver requests to threads?
This seems unneccesarily complicated to me. The usual approach for a multithreaded server is:
Create a listen-socket in a thread process
Accept the client-connections in a thread
For each accepted client connection, create a new threads, which receives the corresponding file descriptor and does the work
The worker thread closes the client connection, when it is fully handled
I do not see much benefit in prepopulating a thread-pool here.
If you really want a threadpool:
I would just use a linked list for accepted connections and a pthread_mutex to synchronize access to it:
The listener-process enqueues client fds at the tail of the list.
The clients dequeue it at the head.
If the queue is empty, the thread can wait on a variable (pthread_cond_wait) and are notified by the listener process (pthread_cond_signal) when connections are available.
Another alternative
Depending on the complexity of handling requests, it might be an option to make the server single-threaded, i.e. handle all connections in one thread. This eliminates context-switches altogether and can thus be very performant.
One drawback is, that only one CPU-core is used. To improve that, a hybrid-model can be used:
Create one worker-thread per core.
Each thread handles simultaneously n connections.
You would however have to implement mechanisms to distribute the work fairly amongst the workers.
In addition to using pthread_mutex, you will want to use pthread_cond_t (pthread condition), this will allow you to put the threads in the thread pool to sleep while they are not actually doing work. Otherwise, you will be wasting compute cycles if they are sitting there in a loop checking for something in the work queue.
I would definitely consider using C++ instead of just pure C. The reason I suggest it is that in C++ you are able to use templates. Using a pure virtual base class (lets call it: "vtask"), you can create templated derived classes that accept arguments and insert the arguments when the overloaded operator() is called, allowing for much, much more functionality in your tasks:
//============================================================================//
void* thread_pool::execute_thread()
{
vtask* task = NULL;
while(true)
{
//--------------------------------------------------------------------//
// Try to pick a task
m_task_lock.lock();
//--------------------------------------------------------------------//
// We need to put condition.wait() in a loop for two reasons:
// 1. There can be spurious wake-ups (due to signal/ENITR)
// 2. When mutex is released for waiting, another thread can be waken up
// from a signal/broadcast and that thread can mess up the condition.
// So when the current thread wakes up the condition may no longer be
// actually true!
while ((m_pool_state != state::STOPPED) && (m_main_tasks.empty()))
{
// Wait until there is a task in the queue
// Unlock mutex while wait, then lock it back when signaled
m_task_cond.wait(m_task_lock.base_mutex_ptr());
}
// If the thread was waked to notify process shutdown, return from here
if (m_pool_state == state::STOPPED)
{
//m_has_exited.
m_task_lock.unlock();
//----------------------------------------------------------------//
if(mad::details::allocator_list_tl::get_allocator_list_if_exists() &&
tids.find(CORETHREADSELF()) != tids.end())
mad::details::allocator_list_tl::get_allocator_list()
->Destroy(tids.find(CORETHREADSELF())->second, 1);
//----------------------------------------------------------------//
CORETHREADEXIT(NULL);
}
task = m_main_tasks.front();
m_main_tasks.pop_front();
//--------------------------------------------------------------------//
//run(task);
// Unlock
m_task_lock.unlock();
//--------------------------------------------------------------------//
// execute the task
run(task);
m_task_count -= 1;
m_join_lock.lock();
m_join_cond.signal();
m_join_lock.unlock();
//--------------------------------------------------------------------//
}
return NULL;
}
//============================================================================//
int thread_pool::add_task(vtask* task)
{
#ifndef ENABLE_THREADING
run(task);
return 0;
#endif
if(!is_alive_flag)
{
run(task);
return 0;
}
// do outside of lock because is thread-safe and needs to be updated as
// soon as possible
m_task_count += 1;
m_task_lock.lock();
// if the thread pool hasn't been initialize, initialize it
if(m_pool_state == state::NONINIT)
initialize_threadpool();
// TODO: put a limit on how many tasks can be added at most
m_main_tasks.push_back(task);
// wake up one thread that is waiting for a task to be available
m_task_cond.signal();
m_task_lock.unlock();
return 0;
}
//============================================================================//
void thread_pool::run(vtask*& task)
{
(*task)();
if(task->force_delete())
{
delete task;
task = 0;
} else {
if(task->get() && !task->is_stored_elsewhere())
save_task(task);
else if(!task->is_stored_elsewhere())
{
delete task;
task = 0;
}
}
}
In the above, each created thread runs execute_thread() until the m_pool_state is set to state::STOPPED. You lock the m_task_lock, and if the state is not STOPPED and the list is empty, you pass the m_task_lock to your condition, which puts the thread to sleep and frees the lock. You create the tasks (not shown), add the task (m_task_count is an atomic, by the way, that is why it is thread safe). During the add task, the condition is signaled to wake up a thread, from which the thread proceeds from the m_task_cond.wait(m_task_lock.base_mutex_ptr()) section of execute_thread() after m_task_lock has been acquired and locked.
NOTE: this is a highly customized implementation that wraps most of the pthread functions/objects into C++ classes so copy-and-pasting will not work whatsoever... Sorry. And w.r.t. the thread_pool::run(), unless you are worrying about return values, the (*task)() line is all you need.
I hope this helps.
EDIT: the m_join_* references is for checking whether all the tasks have been completed. The main thread sits in a similar conditioned wait that checks whether all the tasks have been completed as this is necessary for the applications I use this implementation in before proceeding.

Can't figure out how to implement threads in my client-server model

I have a small server-client application that doesn't do very much (a client connects to the server, sends a number trough a pipe and receives another number).
But it only works with one connection at a time (While a client is connected, no other client has access to the server)
I want to make it possible for multiple clients to connect to the server at one time, and I plan to do this with worker threads.
Obs:
#define CONNECT_NAMEDPIPE "\\\\.\\pipe\\ClientToServer"
Server:
HANDLE namedPipe = CreateNamedPipe (CONNECT_NAMEDPIPE,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
2,
sizeof(MinMax),
sizeof(NumberList),
0, // timeout
NULL);
if (namedPipe == INVALID_HANDLE_VALUE) {
printf("Unable to create named pipe\r\nServer closing\r\n");
printf("CreateNamedPipe failed, GLE=%d.\r\n", GetLastError());
} // Error unable create pipe
else {
printf("Server created\r\n");
printf("Awaiting connection\r\n");
ConnectNamedPipe(namedPipe, NULL);
etc ...
}
So the server waits on ConnectNamedPipe until a client connects, then is unavailable for any other connections.
If I'd like to enable multiple connections, how should I create the worker threads ?
Should every connection attempt create a new pipe (with a new pipe name / path - CONNECT_NAMEDPIPE can't be used for all)
How do I know when someone else is trying to connect ? Where should my threads be ? I'm stuck.
I think Berkeley sockets are better suited for this. If you must go with pipes, something like this could work:
The client sends a connection request through the main named pipe to the control thread.
The server creates (or fetches from a pool) a worker thread that listens on another, unique pipe.
The control thread answers with the name of this new pipe.
The client closes the control pipe and sends real request data to the new pipe.
The worker thread reads the request, processes it, and sends back the response.
Meanwhile the control thread is ready to read another connection request from another client.

Multi-clients on a server

For an application in C, i need to response more than one clients.
I setup the connection with a code like,
bind(...);
listen(...);
while(1){
accept(...);//accept a client
recv(...);//receive something
send(...);//send something to client
bzero(buf);//clear buffer
}
This works great when i have only one client. Other clients also can connect to the server but although they command something, server does not response back to clients who connected after the first client. How can i solve this problem?
Write a server using asynchronous, nonblocking connections.
Instead of a single set of data about a client, you need to create a struct. Each instance of the struct holds the data for each client.
The code looks vaguely like:
socket(...)
fcntl(...) to mark O_NONBLOCK
bind(...)
listen(...)
create poll entry for server socket.
while(1) {
poll(...)
if( fds[server_slot].revents & POLLIN ) {
accept(...)
fcntl(...) mark O_NONBLOCK
create poll and data array entries.
}
if( fds[i].revents & POLLIN ) {
recv(...) into data[i]
if connection i closed then clean up.
}
if( fds[i].revents & POLLOUT ) {
send(...) pending info for data[i]
}
}
If any of your calls return the error EAGAIN instead of success then don't panic. You just try again later. Be prepared for EAGAIN even if poll claims the socket is ready: it's good practice and more robust.
i need to response more than one clients.
Use Threading.
Basically you want your main thread to only do the accept part, and then handle the rest to another thread of execution (which can be either a thread or a process).
Whenever your main thread returns from "accept", give the socket descriptor to another thread, and call accept again (this can be done with fork, with pthread_create, or by maintaining a thread pool and using synchronization, for instance condition variables, to indicate that a new client has been accepted).
While the main thread will handle possible new clients incoming, the other threads will deal with the recv/send.

Resources