Skip to content

Commit 9eee4b9

Browse files
author
Veronica Zheng
committed
Merge pull request #848 from leapmotion/dep-threadpool
Deprecate `CoreContext` thread pools
2 parents 43bd063 + 6e3b667 commit 9eee4b9

File tree

5 files changed

+37
-240
lines changed

5 files changed

+37
-240
lines changed

autowiring/CoreContext.h

-52
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "MemoEntry.h"
2323
#include "once.h"
2424
#include "result_or_default.h"
25-
#include "ThreadPool.h"
2625
#include "TypeRegistry.h"
2726
#include "TypeUnifier.h"
2827

@@ -49,10 +48,6 @@ class CoreContextT;
4948
template<typename T>
5049
class JunctionBox;
5150

52-
namespace autowiring {
53-
class ThreadPool;
54-
}
55-
5651
/// \file
5752
/// CoreContext definitions.
5853

@@ -231,10 +226,6 @@ class CoreContext:
231226
// Actual core threads:
232227
std::list<CoreRunnable*> m_threads;
233228

234-
// The thread pool used by this context. By default, a context inherits the thread pool of
235-
// its parent, and the global context gets the system thread pool.
236-
std::shared_ptr<autowiring::ThreadPool> m_threadPool;
237-
238229
// The start token for the thread pool, if one exists
239230
std::shared_ptr<void> m_startToken;
240231

@@ -1066,49 +1057,6 @@ class CoreContext:
10661057
);
10671058
}
10681059

1069-
/// <summary>
1070-
/// Assigns the thread pool handler for this context
1071-
/// </summary>
1072-
/// <remarks>
1073-
/// If the context is currently running, the thread pool will automatically be started. The pool's
1074-
/// start token and shared pointer is reset automatically when the context is torn down. If the
1075-
/// context has already been shut down (IE, IsShutdown returns true), this method has no effect.
1076-
///
1077-
/// Dispatchers that have been attached to the current thread pool will not be transitioned to the
1078-
/// new pool. Changing the thread pool may cause the previously assigned thread pool to be stopped.
1079-
/// This will cause it to complete all work assigned to it and release resources associated with
1080-
/// processing. If there are no other handles to the pool, it may potentially destroy itself.
1081-
///
1082-
/// It is an error to pass nullptr to this method.
1083-
/// </remarks>
1084-
void SetThreadPool(const std::shared_ptr<autowiring::ThreadPool>& threadPool);
1085-
1086-
/// <summary>
1087-
/// Returns the current thread pool
1088-
/// </summary>
1089-
/// <remarks>
1090-
/// If the context has been shut down, (IE, IsShutdown returns true), this method returns nullptr. Calling
1091-
/// ThreadPool::Start on the returned shared pointer will not cause dispatchers pended to this context to
1092-
/// be executed. To do this, invoke CoreContext::Initiate
1093-
/// </remarks>
1094-
std::shared_ptr<autowiring::ThreadPool> GetThreadPool(void) const;
1095-
1096-
/// <summary>
1097-
/// Submits the specified lambda to this context's ThreadPool for processing
1098-
/// </summary>
1099-
/// <returns>True if the job has been submitted for execution</returns>
1100-
/// <remarks>
1101-
/// The passed thunk will not be executed if the current context has already stopped.
1102-
/// </remarks>
1103-
template<class Fx>
1104-
bool operator+=(Fx&& fx) {
1105-
auto pool = GetThreadPool();
1106-
return
1107-
pool ?
1108-
pool->Submit(std::make_unique<DispatchThunk<Fx>>(std::forward<Fx&&>(fx))) :
1109-
false;
1110-
}
1111-
11121060
/// <summary>
11131061
/// Adds a post-attachment listener in this context for a particular autowired member.
11141062
/// There is no guarantee for the context in which the listener will be called.

autowiring/SystemThreadPoolStl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#pragma once
33
#include "DispatchQueue.h"
44
#include "SystemThreadPool.h"
5-
#include <thread>
5+
#include <thread>
66
#include <vector>
77

88
namespace autowiring {

autowiring/ThreadPool.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
22
#pragma once
3+
#include "DispatchThunk.h"
34
#include <atomic>
4-
#include <memory>
55
#include <mutex>
6+
#include MEMORY_HEADER
67

78
class DispatchQueue;
89
class DispatchThunkBase;
@@ -89,6 +90,18 @@ class ThreadPool:
8990
/// be submitted for execution.
9091
/// </remarks>
9192
virtual bool Submit(std::unique_ptr<DispatchThunkBase>&& thunk) = 0;
93+
94+
/// <summary>
95+
/// Submits the specified lambda to this context's ThreadPool for processing
96+
/// </summary>
97+
/// <returns>True if the job has been submitted for execution</returns>
98+
/// <remarks>
99+
/// The passed thunk will not be executed if the current context has already stopped.
100+
/// </remarks>
101+
template<class Fx>
102+
bool operator+=(Fx&& fx) {
103+
return Submit(std::make_unique<DispatchThunk<Fx>>(std::forward<Fx&&>(fx)));
104+
}
92105
};
93106

94107
}

src/autowiring/CoreContext.cpp

+1-86
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "NullPool.h"
1313
#include "SystemThreadPool.h"
1414
#include "thread_specific_ptr.h"
15-
#include "ThreadPool.h"
1615
#include <sstream>
1716
#include <stdexcept>
1817

@@ -58,8 +57,7 @@ CoreContext::CoreContext(const std::shared_ptr<CoreContext>& pParent, t_childLis
5857
m_backReference(backReference),
5958
m_sigilType(sigilType),
6059
m_stateBlock(std::make_shared<CoreContextStateBlock>(pParent ? pParent->m_stateBlock : nullptr)),
61-
m_junctionBoxManager(new JunctionBoxManager),
62-
m_threadPool(std::make_shared<NullPool>())
60+
m_junctionBoxManager(new JunctionBoxManager)
6361
{}
6462

6563
CoreContext::~CoreContext(void) {
@@ -448,48 +446,10 @@ void CoreContext::Initiate(void) {
448446

449447
// Now we can recover the first thread that will need to be started
450448
auto beginning = m_threads.begin();
451-
452-
// Start our threads before starting any child contexts:
453-
std::shared_ptr<ThreadPool> threadPool;
454-
auto nullPool = std::dynamic_pointer_cast<NullPool>(m_threadPool);
455-
if (nullPool) {
456-
// Decide which pool will become our current thread pool. Global context is the final case,
457-
// which defaults to the system thread pool
458-
if (!nullPool->GetSuccessor())
459-
nullPool->SetSuccessor(m_pParent ? m_pParent->GetThreadPool() : SystemThreadPool::New());
460-
461-
// Trigger null pool destruction at this point:
462-
m_threadPool = nullPool->MoveDispatchersToSuccessor();
463-
}
464-
465-
// The default case should not generally occur, but if it were the case that the null pool were
466-
// updated before the context was initiated, then we would have no work to do as no successors
467-
// exist to be moved. In that case, simply take a record of the current thread pool for the
468-
// call to Start that follows the unlock.
469-
threadPool = m_threadPool;
470449
lk.unlock();
471450
onInitiated();
472451
m_stateBlock->m_stateChanged.notify_all();
473452

474-
// Start the thread pool out of the lock, and then update our start token if our thread pool
475-
// reference has not changed. The next pool could potentially be nullptr if the parent is going
476-
// down while we are going up.
477-
if (threadPool) {
478-
// Initiate
479-
auto startToken = threadPool->Start();
480-
481-
// Transfer all dispatchers from the null pool to the new thread pool:
482-
std::lock_guard<std::mutex> lk(m_stateBlock->m_lock);
483-
484-
// If the thread pool was updated while we were trying to start the pool we observed earlier,
485-
// then allow our token to expire and do not do any other work. Whomever caused the thread
486-
// pool pointer to be updated would also have seen that the context is currently started,
487-
// and would have updated both the thread pool pointer and the start token at the same time.
488-
if (m_threadPool == threadPool)
489-
// Swap, not assign; we don't want teardown to happen while synchronized
490-
std::swap(m_startToken, startToken);
491-
}
492-
493453
if (beginning != m_threads.end()) {
494454
auto outstanding = m_stateBlock->IncrementOutstandingThreadCount(shared_from_this());
495455
for (auto q = beginning; q != m_threads.end(); ++q)
@@ -552,16 +512,13 @@ void CoreContext::SignalShutdown(bool wait, ShutdownMode shutdownMode) {
552512

553513
// Thread pool token and pool pointer
554514
std::shared_ptr<void> startToken;
555-
std::shared_ptr<ThreadPool> threadPool;
556515

557516
// Tear down all the children, evict thread pool:
558517
{
559518
std::lock_guard<std::mutex> lk(m_stateBlock->m_lock);
560519

561520
startToken = std::move(m_startToken);
562521
m_startToken.reset();
563-
threadPool = std::move(m_threadPool);
564-
m_threadPool.reset();
565522

566523
// Fill strong lock series in order to ensure proper teardown interleave:
567524
childrenInterleave.reserve(m_children.size());
@@ -717,48 +674,6 @@ void CoreContext::BuildCurrentState(void) {
717674
}
718675
}
719676

720-
void CoreContext::SetThreadPool(const std::shared_ptr<ThreadPool>& threadPool) {
721-
if (!threadPool)
722-
throw std::invalid_argument("A context cannot be given a null thread pool");
723-
724-
std::shared_ptr<ThreadPool> priorThreadPool;
725-
{
726-
std::lock_guard<std::mutex> lk(m_stateBlock->m_lock);
727-
if (IsShutdown())
728-
// Nothing to do, context already down
729-
return;
730-
731-
if (!IsRunning()) {
732-
// Just set up the forwarding thread pool
733-
auto nullPool = std::dynamic_pointer_cast<NullPool>(m_threadPool);
734-
if (!nullPool)
735-
throw autowiring_error("Internal error, null pool was deassigned even though the context has not been started");
736-
priorThreadPool = nullPool->GetSuccessor();
737-
nullPool->SetSuccessor(threadPool);
738-
return;
739-
}
740-
741-
priorThreadPool = m_threadPool;
742-
m_threadPool = threadPool;
743-
}
744-
745-
// We are presently running. We need to start the pool, and then attempt to
746-
// update our token
747-
auto startToken = threadPool->Start();
748-
std::lock_guard<std::mutex> lk(m_stateBlock->m_lock);
749-
if (m_threadPool != threadPool)
750-
// Thread pool was updated by someone else, let them complete their operation
751-
return;
752-
753-
// Update our start token and return. Swap, not move; we don't want to risk
754-
// calling destructors while synchronized.
755-
std::swap(m_startToken, startToken);
756-
}
757-
758-
std::shared_ptr<ThreadPool> CoreContext::GetThreadPool(void) const {
759-
return (std::lock_guard<std::mutex>)m_stateBlock->m_lock, m_threadPool;
760-
}
761-
762677
void CoreContext::Dump(std::ostream& os) const {
763678
std::lock_guard<std::mutex> lk(m_stateBlock->m_lock);
764679

0 commit comments

Comments
 (0)