aboutsummaryrefslogtreecommitdiffstats
path: root/include/distortos/internal/memory/DeferredThreadDeleter.hpp
blob: bb38ebc6628325f57ea5d0e2492ba67de3601b89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
 * \file
 * \brief DeferredThreadDeleter class header
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_INTERNAL_MEMORY_DEFERREDTHREADDELETER_HPP_
#define INCLUDE_DISTORTOS_INTERNAL_MEMORY_DEFERREDTHREADDELETER_HPP_

#include "distortos/distortosConfiguration.h"

#ifdef CONFIG_THREAD_DETACH_ENABLE

#include "distortos/Mutex.hpp"

namespace distortos
{

namespace internal
{

/// DeferredThreadDeleter class can be used to defer deletion of dynamic detached threads
class DeferredThreadDeleter
{
public:

	/**
	 * \brief DeferredThreadDeleter's constructor
	 */

	constexpr DeferredThreadDeleter() :
			list_{},
			mutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
			notEmpty_{}
	{

	}

	/**
	 * \brief DeferredThreadDeleter's function call operator
	 *
	 * Adds thread to internal list of threads scheduled for deferred deletion and marks the list as "not empty".
	 *
	 * \note The object must be locked (with a successful call to DeferredThreadDeleter::lock()) before this function is
	 * used!
	 *
	 * \param [in] threadControlBlock is a reference to ThreadControlBlock object associated with dynamic and detached
	 * thread that has terminated its execution
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by Mutex::unlock();
	 */

	int operator()(ThreadControlBlock& threadControlBlock);

	/**
	 * \brief Locks the object, preparing it for adding thread to internal list.
	 *
	 * Locks the mutex that synchronizes access to internal list. Locking (performed in this function) and unlocking
	 * (performed at the end of function call operator) are separated, because the locking must be done while the thread
	 * is still runnable, while the transfer to internal list is performed when the thread is not in this state.
	 *
	 * \note This function must be called before function call operator is used!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by Mutex::lock();
	 */

	int lock();

	/**
	 * \brief Tries to perform deferred deletion of threads.
	 *
	 * Does nothing is the list is not marked as "not empty". Otherwise this function first tries to lock following two
	 * mutexes:
	 * - mutex that protects dynamic memory allocator;
	 * - mutex that synchronizes access to list of threads scheduled for deferred deletion;
	 * If any Mutex::tryLock() call fails, this function just returns (unlocking any mutexes is necessary). Otherwise
	 * the threads are removed from the list and deleted, while the list's "not empty" marker is cleared.
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by Mutex::tryLock();
	 * - error codes returned by Mutex::unlock();
	 */

	int tryCleanup();

private:

	/**
	 * \brief Internals of tryCleanup().
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by Mutex::tryLock();
	 * - error codes returned by Mutex::unlock();
	 */

	int tryCleanupInternal();

	/// list of threads scheduled for deferred deletion
	ThreadList::UnsortedIntrusiveList list_;

	/// mutex that synchronizes access to the \a list_
	Mutex mutex_;

	/// true if \a list_ is not empty, false otherwise
	bool notEmpty_;
};

}	// namespace internal

}	// namespace distortos

#endif	// def CONFIG_THREAD_DETACH_ENABLE

#endif	// INCLUDE_DISTORTOS_INTERNAL_MEMORY_DEFERREDTHREADDELETER_HPP_