mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 18:48:20 +00:00
Threading changes for the new loop architecture
- threading::Manager is no longer an IOSource. - threading::MsgThread is now an IOSource. This allows threads themselves to signal when they have data to process instead of continually checking each of the threads on every loop pass. - Make the thread heartbeat timer an actual timer and let it fire as necessary instead of checking to see if it should fire
This commit is contained in:
parent
a159d075cf
commit
8b9160fb7e
6 changed files with 141 additions and 66 deletions
|
@ -1,33 +1,44 @@
|
|||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Manager.h"
|
||||
#include "NetVar.h"
|
||||
#include "iosource/Manager.h"
|
||||
|
||||
using namespace threading;
|
||||
|
||||
void HeartbeatTimer::Dispatch(double t, int is_expire)
|
||||
{
|
||||
if ( is_expire )
|
||||
return;
|
||||
|
||||
thread_mgr->SendHeartbeats();
|
||||
thread_mgr->StartHeartbeatTimer();
|
||||
}
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
DBG_LOG(DBG_THREADING, "Creating thread manager ...");
|
||||
|
||||
did_process = true;
|
||||
next_beat = 0;
|
||||
terminating = false;
|
||||
SetIdle(true);
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
if ( all_threads.size() )
|
||||
Terminate();
|
||||
|
||||
if ( heartbeat_timer )
|
||||
delete heartbeat_timer;
|
||||
}
|
||||
|
||||
void Manager::Terminate()
|
||||
{
|
||||
DBG_LOG(DBG_THREADING, "Terminating thread manager ...");
|
||||
|
||||
terminating = true;
|
||||
|
||||
// First process remaining thread output for the message threads.
|
||||
do Process(); while ( did_process );
|
||||
do Flush(); while ( did_process );
|
||||
|
||||
// Signal all to stop.
|
||||
|
||||
|
@ -46,17 +57,15 @@ void Manager::Terminate()
|
|||
|
||||
all_threads.clear();
|
||||
msg_threads.clear();
|
||||
|
||||
SetIdle(true);
|
||||
SetClosed(true);
|
||||
terminating = false;
|
||||
}
|
||||
|
||||
void Manager::AddThread(BasicThread* thread)
|
||||
{
|
||||
DBG_LOG(DBG_THREADING, "Adding thread %s ...", thread->Name());
|
||||
all_threads.push_back(thread);
|
||||
SetIdle(false);
|
||||
|
||||
if ( ! heartbeat_timer )
|
||||
StartHeartbeatTimer();
|
||||
}
|
||||
|
||||
void Manager::AddMsgThread(MsgThread* thread)
|
||||
|
@ -65,34 +74,6 @@ void Manager::AddMsgThread(MsgThread* thread)
|
|||
msg_threads.push_back(thread);
|
||||
}
|
||||
|
||||
void Manager::GetFds(iosource::FD_Set* read, iosource::FD_Set* write,
|
||||
iosource::FD_Set* except)
|
||||
{
|
||||
}
|
||||
|
||||
double Manager::NextTimestamp(double* network_time)
|
||||
{
|
||||
// fprintf(stderr, "N %.6f %.6f did_process=%d next_next=%.6f\n", ::network_time, timer_mgr->Time(), (int)did_process, next_beat);
|
||||
|
||||
if ( ::network_time && (did_process || ::network_time > next_beat || ! next_beat) )
|
||||
// If we had something to process last time (or out heartbeat
|
||||
// is due or not set yet), we want to check for more asap.
|
||||
return timer_mgr->Time();
|
||||
|
||||
for ( msg_thread_list::iterator i = msg_threads.begin(); i != msg_threads.end(); i++ )
|
||||
{
|
||||
MsgThread* t = *i;
|
||||
|
||||
if ( t->MightHaveOut() || t->Killed() )
|
||||
// Even if the thread doesn't have output, it may be killed/done,
|
||||
// which should also signify that processing is needed. The
|
||||
// "processing" in that case is joining the thread and deleting it.
|
||||
return timer_mgr->Time();
|
||||
}
|
||||
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
void Manager::KillThreads()
|
||||
{
|
||||
DBG_LOG(DBG_THREADING, "Killing threads ...");
|
||||
|
@ -107,7 +88,46 @@ void Manager::KillThread(BasicThread* thread)
|
|||
thread->Kill();
|
||||
}
|
||||
|
||||
void Manager::Process()
|
||||
void Manager::SendHeartbeats()
|
||||
{
|
||||
for ( MsgThread* thread : msg_threads )
|
||||
thread->Heartbeat();
|
||||
|
||||
// Since this is a regular timer, this is also an ideal place to check whether we have
|
||||
// and dead threads and to delete them.
|
||||
all_thread_list to_delete;
|
||||
for ( all_thread_list::iterator i = all_threads.begin(); i != all_threads.end(); i++ )
|
||||
{
|
||||
BasicThread* t = *i;
|
||||
|
||||
if ( t->Killed() )
|
||||
to_delete.push_back(t);
|
||||
}
|
||||
|
||||
for ( all_thread_list::iterator i = to_delete.begin(); i != to_delete.end(); i++ )
|
||||
{
|
||||
BasicThread* t = *i;
|
||||
t->WaitForStop();
|
||||
|
||||
all_threads.remove(t);
|
||||
|
||||
MsgThread* mt = dynamic_cast<MsgThread *>(t);
|
||||
|
||||
if ( mt )
|
||||
msg_threads.remove(mt);
|
||||
|
||||
t->Join();
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::StartHeartbeatTimer()
|
||||
{
|
||||
heartbeat_timer = new HeartbeatTimer(network_time + BifConst::Threading::heartbeat_interval);
|
||||
timer_mgr->Add(heartbeat_timer);
|
||||
}
|
||||
|
||||
void Manager::Flush()
|
||||
{
|
||||
bool do_beat = false;
|
||||
|
||||
|
@ -192,5 +212,3 @@ const threading::Manager::msg_stats_list& threading::Manager::GetMsgThreadStats(
|
|||
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue