int main(int argc, const char **argv) { try { if (argc != 5) { std::cerr << "Usage: " << argv[0] << " CONNECTION-URL AMQP-ADDRESS MESSAGE-COUNT THREAD-COUNT\n" "CONNECTION-URL: connection address, e.g.'amqp://127.0.0.1'\n" "AMQP-ADDRESS: AMQP node address, e.g. 'examples'\n" "MESSAGE-COUNT: number of messages to send\n" "THREAD-COUNT: number of sender/receiver thread pairs\n"; return 1; } const char *url = argv[1]; const char *address = argv[2]; int n_messages = atoi(argv[3]); int n_threads = atoi(argv[4]); int count = n_messages * n_threads; // Total messages to be received, multiple receiver threads will decrement this. std::atomic_int remaining; remaining.store(count); // Run the proton container proton::container container; auto container_thread = std::thread([&]() { container.run(); }); // A single sender and receiver to be shared by all the threads sender send(container, url, address); receiver recv(container, url, address); // Start receiver threads, then sender threads. // Starting receivers first gives all receivers a chance to compete for messages. std::vector<std::thread> threads; threads.reserve(n_threads*2); // Avoid re-allocation once threads are started for (int i = 0; i < n_threads; ++i) threads.push_back(std::thread([&]() { receive_thread(recv, remaining); })); for (int i = 0; i < n_threads; ++i) threads.push_back(std::thread([&]() { send_thread(send, n_messages); })); // Wait for threads to finish for (auto& t : threads) t.join(); send.close(); recv.close(); container_thread.join(); if (remaining > 0) throw std::runtime_error("not all messages were received"); std::cout << count << " messages sent and received" << std::endl; return 0; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } return 1; }
void hastd_secondary(struct hast_resource *res, struct nv *nvin) { sigset_t mask; pthread_t td; pid_t pid; int error, mode, debuglevel; /* * Create communication channel between parent and child. */ if (proto_client(NULL, "socketpair://", &res->hr_ctrl) < 0) { KEEP_ERRNO((void)pidfile_remove(pfh)); pjdlog_exit(EX_OSERR, "Unable to create control sockets between parent and child"); } /* * Create communication channel between child and parent. */ if (proto_client(NULL, "socketpair://", &res->hr_event) < 0) { KEEP_ERRNO((void)pidfile_remove(pfh)); pjdlog_exit(EX_OSERR, "Unable to create event sockets between child and parent"); } pid = fork(); if (pid < 0) { KEEP_ERRNO((void)pidfile_remove(pfh)); pjdlog_exit(EX_OSERR, "Unable to fork"); } if (pid > 0) { /* This is parent. */ proto_close(res->hr_remotein); res->hr_remotein = NULL; proto_close(res->hr_remoteout); res->hr_remoteout = NULL; /* Declare that we are receiver. */ proto_recv(res->hr_event, NULL, 0); /* Declare that we are sender. */ proto_send(res->hr_ctrl, NULL, 0); res->hr_workerpid = pid; return; } gres = res; mode = pjdlog_mode_get(); debuglevel = pjdlog_debug_get(); /* Declare that we are sender. */ proto_send(res->hr_event, NULL, 0); /* Declare that we are receiver. */ proto_recv(res->hr_ctrl, NULL, 0); descriptors_cleanup(res); descriptors_assert(res, mode); pjdlog_init(mode); pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role)); setproctitle("%s (%s)", res->hr_name, role2str(res->hr_role)); PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); /* Error in setting timeout is not critical, but why should it fail? */ if (proto_timeout(res->hr_remotein, 2 * HAST_KEEPALIVE) < 0) pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); if (proto_timeout(res->hr_remoteout, res->hr_timeout) < 0) pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); init_local(res); init_environment(); if (drop_privs(res) != 0) exit(EX_CONFIG); pjdlog_info("Privileges successfully dropped."); /* * Create the control thread before sending any event to the parent, * as we can deadlock when parent sends control request to worker, * but worker has no control thread started yet, so parent waits. * In the meantime worker sends an event to the parent, but parent * is unable to handle the event, because it waits for control * request response. */ error = pthread_create(&td, NULL, ctrl_thread, res); PJDLOG_ASSERT(error == 0); init_remote(res, nvin); event_send(res, EVENT_CONNECT); error = pthread_create(&td, NULL, recv_thread, res); PJDLOG_ASSERT(error == 0); error = pthread_create(&td, NULL, disk_thread, res); PJDLOG_ASSERT(error == 0); (void)send_thread(res); }