Skip to content

Commit 281b69b

Browse files
committed
More API polishing. Really starting to look clean and enforces a lot of good habits.
1 parent babd2bc commit 281b69b

18 files changed

+754
-779
lines changed

src/include/ptk_buf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ extern ptk_err ptk_buf_set_end(ptk_buf *buf, buf_size_t end);
120120
*/
121121
extern ptk_err ptk_buf_move_block(ptk_buf *buf, buf_size_t new_position);
122122

123-
/* no ptk_buf_free() because that it taken care of by ptk_alloc() */
123+
/* Use ptk_local_free() to free buffers allocated with ptk_buf_alloc() */
124124

125125
//=============================================================================
126126
// SIMPLE BYTE ACCESS API

src/include/ptk_mem.h

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,48 @@ extern void ptk_local_free_impl(const char *file, int line, void **ptr_ref);
171171

172172

173173
typedef struct ptk_shared_handle {
174-
uint64_t value; // Opaque handle value
174+
uintptr_t value; // Opaque handle value
175175
} ptk_shared_handle_t;
176176

177177
#define PTK_SHARED_INVALID_HANDLE ((ptk_shared_handle_t){0})
178178
#define PTK_SHARED_IS_VALID(h) ((h).value != 0)
179179
#define PTK_SHARED_HANDLE_EQUAL(a,b) ((a).value == (b).value)
180180

181-
#define ptk_shared_create(ptr) ptk_shared_create_impl(__FILE__, __LINE__, ptr)
182-
extern ptk_shared_handle_t ptk_shared_create_impl(const char *file, int line, void *ptr);
183-
181+
/**
182+
* @brief Initialize the shared memory subsystem.
183+
*
184+
* @return ptk_err status code
185+
* @retval PTK_OK on success
186+
*/
184187
extern ptk_err ptk_shared_init(void);
188+
189+
/**
190+
* @brief Shut down the shared memory subsystem.
191+
*
192+
* @return ptk_err status code
193+
* @retval PTK_OK on success
194+
*/
185195
extern ptk_err ptk_shared_shutdown(void);
186196

187-
extern void *ptk_shared_acquire(ptk_shared_handle_t handle);
188-
extern ptk_err ptk_shared_realloc(ptk_shared_handle_t handle, size_t new_size); // reuses the existing handle.
189-
extern ptk_err ptk_shared_release(ptk_shared_handle_t handle);
197+
198+
/**
199+
* @brief Allocate a shared memory block.
200+
*
201+
* @param size Size of the memory block to allocate
202+
* @param destructor Optional destructor function for the memory block
203+
* @return ptk_shared_handle_t Handle to the allocated memory, or PTK_SHARED_INVALID_HANDLE on failure
204+
*/
205+
#define ptk_shared_alloc(size, destructor) ptk_shared_alloc_impl(__FILE__, __LINE__, size, destructor)
206+
extern ptk_shared_handle_t ptk_shared_alloc_impl(const char *file, int line, size_t size, void (*destructor)(void *ptr));
207+
208+
#define ptk_shared_realloc(handle, new_size) ptk_shared_realloc_impl(__FILE__, __LINE__, handle, new_size)
209+
extern ptk_err ptk_shared_realloc_impl(const char *file, int line, ptk_shared_handle_t handle, size_t new_size); // reuses the existing handle.
210+
211+
#define ptk_shared_acquire(handle, timeout) ptk_shared_acquire_impl(__FILE__, __LINE__, handle, timeout)
212+
extern void *ptk_shared_acquire_impl(const char *file, int line, ptk_shared_handle_t handle, ptk_time_ms timeout);
213+
214+
#define ptk_shared_release(handle) ptk_shared_release_impl(__FILE__, __LINE__, handle)
215+
extern ptk_err ptk_shared_release_impl(const char *file, int line, ptk_shared_handle_t handle);
190216

191217
/**
192218
* @brief Macro for safely using shared memory with automatic acquire/release
@@ -195,22 +221,26 @@ extern ptk_err ptk_shared_release(ptk_shared_handle_t handle);
195221
* handling acquire/release operations and providing error handling.
196222
*
197223
* Usage:
198-
* use_shared(handle, my_struct_t *obj) {
224+
* use_shared(handle, timeout_ms, my_struct_t *obj) {
199225
* // Code that uses obj - obj is automatically cast to the correct type
200226
* obj->field = value;
201227
* } on_shared_fail {
202-
* // Error handling code - runs if acquire fails
228+
* // Error handling code - runs if acquire fails or times out
203229
* error("Failed to acquire shared memory");
204230
* }
205231
*
206232
* @param handle The shared memory handle to acquire
233+
* @param timeout_ms Timeout in milliseconds (use PTK_TIME_WAIT_FOREVER or PTK_TIME_NO_WAIT)
207234
* @param declaration The typed pointer declaration (e.g., "my_struct_t *obj")
235+
*
236+
* NOTE: ptk_shared_release_impl must be called even if the return value is NULL, to avoid leaks.
237+
* The macro ensures this happens automatically.
208238
*/
209-
#define use_shared(handle, declaration) \
239+
#define use_shared(handle, timeout_ms, declaration) \
210240
for (int _ptk_shared_once = 0; _ptk_shared_once < 1; _ptk_shared_once++) \
211-
for (void *_ptk_shared_raw_ptr = ptk_shared_acquire(handle); \
241+
for (void *_ptk_shared_raw_ptr = ptk_shared_acquire_impl(__FILE__, __LINE__, handle, timeout_ms); \
212242
_ptk_shared_once < 1; \
213-
_ptk_shared_once++, (_ptk_shared_raw_ptr ? ptk_shared_release(handle) : (void)0)) \
243+
_ptk_shared_once++, ptk_shared_release_impl(__FILE__, __LINE__, handle)) \
214244
if (_ptk_shared_raw_ptr != NULL) \
215245
for (declaration = (typeof(declaration))_ptk_shared_raw_ptr; \
216246
_ptk_shared_raw_ptr != NULL; \

src/include/ptk_os_thread.h

Lines changed: 107 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -28,117 +28,172 @@
2828
#include <stdint.h>
2929
#include <stddef.h>
3030
#include <stdbool.h>
31-
3231
// Forward declarations to break circular dependencies
3332
typedef enum ptk_err ptk_err;
33+
typedef struct ptk_shared_handle ptk_shared_handle_t;
3434
typedef int64_t ptk_time_ms;
3535

36+
// Timeout constants (from ptk_utils.h)
37+
#define PTK_TIME_WAIT_FOREVER (INT64_MAX)
38+
#define PTK_TIME_NO_WAIT (INT64_MIN)
39+
3640
#if defined(_WIN32) && defined(_MSC_VER)
3741
#define ptk_thread_local __declspec(thread)
3842
#else
3943
#define ptk_thread_local __thread
4044
#endif
4145

4246

47+
/* Mutex and condition variable types removed from public API.
48+
* Use shared memory handles for synchronization instead:
49+
* - Data protection: use_shared() macro provides automatic synchronization
50+
* - Thread communication: ptk_thread_signal() and ptk_thread_wait()
51+
* - OS-native mutexes used internally by shared memory implementation only
52+
*/
53+
4354
/**
44-
* @brief Forward declaration of a mutex type.
55+
* @brief Thread handle type (uses shared memory for safe cross-thread access)
4556
*/
46-
typedef struct ptk_mutex ptk_mutex;
57+
typedef ptk_shared_handle_t ptk_thread_handle_t;
4758

4859
/**
49-
* @brief Forward declaration of a condition variable type.
60+
* @brief No parent constant for root threads
5061
*/
51-
typedef struct ptk_cond_var ptk_cond_var;
62+
#define PTK_THREAD_NO_PARENT PTK_SHARED_INVALID_HANDLE
5263

5364
/**
54-
* @brief Forward declaration of a thread type.
65+
* @brief Thread signal types for unified signaling API
66+
*/
67+
typedef enum {
68+
PTK_THREAD_SIGNAL_WAKEUP, // General wake-up signal
69+
PTK_THREAD_SIGNAL_ABORT, // Request graceful shutdown
70+
PTK_THREAD_SIGNAL_TERMINATE, // Force immediate termination
71+
PTK_THREAD_SIGNAL_CHILD_DIED // Child death notification (automatic)
72+
} ptk_thread_signal_t;
73+
74+
/* Public mutex and condition variable APIs removed.
75+
* Synchronization handled by shared memory system:
76+
*
77+
* Instead of mutexes, use shared memory access patterns:
78+
* use_shared(data_handle, timeout, my_data_t *data) {
79+
* // Automatically synchronized access to data
80+
* } on_shared_fail {
81+
* // Handle timeout or failure
82+
* }
83+
*
84+
* Instead of condition variables, use thread signals:
85+
* ptk_thread_signal(worker_thread); // Wake up waiting thread
86+
* ptk_thread_wait(handle, timeout); // Wait for signal
5587
*/
56-
typedef struct ptk_thread ptk_thread;
5788

5889
//============================
59-
// Mutex Functions
90+
// Thread Functions
6091
//============================
6192

6293
/**
63-
* @brief Creates a new recursive mutex.
94+
* @brief Function type for thread entry points.
6495
*
65-
* @param allocator The allocator to use for creating the mutex
66-
* @return Pointer to the newly created mutex, or NULL on failure
96+
* @param data Shared memory handle containing user data for the thread.
6797
*/
68-
extern ptk_mutex *ptk_mutex_create(void);
98+
typedef void (*ptk_thread_func)(ptk_shared_handle_t data);
6999

70100
/**
71-
* @brief Attempts to lock the mutex, optionally waiting for a timeout.
101+
* @brief Creates and starts a new thread with parent-child relationship.
102+
*
103+
* Child threads automatically register with parent and signal parent when they die.
104+
* Use PTK_THREAD_NO_PARENT for root threads.
72105
*
73-
* @param mutex Pointer to the mutex.
74-
* @param timeout_ms Timeout in milliseconds. Use PTK_TIME_NO_WAIT or PTK_TIME_WAIT_FOREVER for special cases.
75-
* @return Error code.
106+
* @param parent Parent thread handle, or PTK_THREAD_NO_PARENT for root threads
107+
* @param func Entry point for the thread function
108+
* @param data User data to pass to the thread function (shared memory handle)
109+
* @return Thread handle for the new thread, or PTK_SHARED_INVALID_HANDLE on failure
76110
*/
77-
extern ptk_err ptk_mutex_wait_lock(ptk_mutex *mutex, ptk_time_ms timeout_ms);
111+
extern ptk_thread_handle_t ptk_thread_create(ptk_thread_handle_t parent,
112+
ptk_thread_func func,
113+
ptk_shared_handle_t data);
78114

79115
/**
80-
* @brief Unlocks the previously locked mutex.
116+
* @brief Get the current thread's handle.
81117
*
82-
* @param mutex Pointer to the mutex.
83-
* @return Error code.
118+
* @return Handle for the calling thread
84119
*/
85-
extern ptk_err ptk_mutex_unlock(ptk_mutex *mutex);
86-
87-
//============================
88-
// Condition Variable Functions
89-
//============================
120+
extern ptk_thread_handle_t ptk_thread_self(void);
90121

91122
/**
92-
* @brief Creates a condition variable.
123+
* @brief Wait for signals or timeout (calling thread waits for itself).
93124
*
94-
* @param allocator The allocator to use for creating the condition variable
95-
* @return Pointer to the created condition variable, or NULL on failure
125+
* The calling thread waits until signaled or timeout occurs. Socket operations
126+
* (like ptk_tcp_accept) also wake up on any signal for responsive server loops.
127+
*
128+
* @param timeout_ms Timeout in milliseconds
129+
* @return PTK_OK on timeout, PTK_SIGNAL if signaled (check ptk_thread_get_last_signal())
96130
*/
97-
extern ptk_cond_var *ptk_cond_var_create(void);
131+
extern ptk_err ptk_thread_wait(ptk_time_ms timeout_ms);
98132

99133
/**
100-
* @brief Signals the condition variable, waking one waiting thread.
134+
* @brief Send a signal to a thread.
135+
*
136+
* Signals cause the target thread to wake up from ptk_thread_wait() or socket
137+
* operations like ptk_tcp_accept(). The thread can check the signal type.
101138
*
102-
* @param cond_var Pointer to the condition variable.
103-
* @return Error code.
139+
* @param handle Thread handle to signal
140+
* @param signal_type Type of signal to send
141+
* @return Error code
104142
*/
105-
extern ptk_err ptk_cond_var_signal(ptk_cond_var *cond_var);
143+
extern ptk_err ptk_thread_signal(ptk_thread_handle_t handle, ptk_thread_signal_t signal_type);
106144

107145
/**
108-
* @brief Waits for the condition variable to be signaled.
146+
* @brief Get the last signal received by the calling thread.
147+
*
148+
* Call this after ptk_thread_wait() returns PTK_SIGNAL to determine what signal was received.
109149
*
110-
* @param cond_var Pointer to the condition variable.
111-
* @param mutex Pointer to an already locked mutex that will be released during the wait.
112-
* @param timeout_ms Timeout in milliseconds. Use THREAD_NO_WAIT or THREAD_WAIT_FOREVER for special cases.
113-
* @return Error code.
150+
* @return The last signal type received, or PTK_THREAD_SIGNAL_WAKEUP if none
114151
*/
115-
extern ptk_err ptk_cond_var_wait(ptk_cond_var *cond_var, ptk_mutex *mutex, ptk_time_ms timeout_ms);
152+
extern ptk_thread_signal_t ptk_thread_get_last_signal(void);
116153

117154
//============================
118-
// Thread Functions
155+
// Parent-Child Thread Management
119156
//============================
120157

121158
/**
122-
* @brief Function type for thread entry points.
159+
* @brief Get the parent thread handle.
160+
*
161+
* @param thread Thread handle to query (use ptk_thread_self() for current thread)
162+
* @return Parent thread handle, or PTK_THREAD_NO_PARENT if no parent
163+
*/
164+
extern ptk_thread_handle_t ptk_thread_get_parent(ptk_thread_handle_t thread);
165+
166+
/**
167+
* @brief Count the number of child threads.
123168
*
124-
* @param data Pointer to user data passed to the thread.
169+
* Child threads are automatically tracked. This returns the current count.
170+
*
171+
* @param parent Parent thread handle
172+
* @return Number of active child threads
125173
*/
126-
typedef void (*ptk_thread_func)(void *data);
174+
extern int ptk_thread_count_children(ptk_thread_handle_t parent);
127175

128176
/**
129-
* @brief Creates and starts a new thread.
177+
* @brief Signal all child threads.
178+
*
179+
* Sends the same signal to all children of the specified parent thread.
180+
* Useful for coordinated shutdown or other broadcast operations.
130181
*
131-
* @param func Entry point for the thread function.
132-
* @param data User data to pass to the thread function.
133-
* @return Pointer to the created thread handle, or NULL on failure
182+
* @param parent Parent thread handle
183+
* @param signal_type Signal to send to all children
184+
* @return Error code
134185
*/
135-
extern ptk_thread *ptk_thread_create(ptk_thread_func func, void *data);
186+
extern ptk_err ptk_thread_signal_all_children(ptk_thread_handle_t parent, ptk_thread_signal_t signal_type);
136187

137188
/**
138-
* @brief Waits for the specified thread to complete.
189+
* @brief Clean up dead child threads.
190+
*
191+
* Attempts to release handles for child threads that have died. Uses timeout
192+
* to avoid blocking. Call with PTK_TIME_NO_WAIT for immediate cleanup only.
139193
*
140-
* @param thread Thread to join.
141-
* @return Error code.
194+
* @param parent Parent thread handle
195+
* @param timeout_ms Maximum time to wait for cleanup
196+
* @return Error code
142197
*/
143-
extern ptk_err ptk_thread_join(ptk_thread *thread);
198+
extern ptk_err ptk_thread_cleanup_dead_children(ptk_thread_handle_t parent, ptk_time_ms timeout_ms);
144199

0 commit comments

Comments
 (0)