mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-08-17 17:31:44 +08:00
3.8 KiB
3.8 KiB
Coding Convention (Multi-Threading)
- Most of the code do not require thread safety, DO NOT over engineering.
SpinLockis only for protecting a piece of code or data in a super flashy short time.- When defining a
SpinLockfield, names it begins withlock, a// covers a, b, ccomment is recommended to put above it, a empty line is recommended to put around it. - When doing
read-process-writebut thewritepart doesn't depend on the result ofprocess:- The below rules only involve when
processis heavy, if anything is simple, keep it simple. - You can copy or move the heavy structure in
SPIN_LOCK, andprocessafterSPIN_LOCK. - Especially for scenario when a container should be processed and cleared,
std::movewould be the best choice to copy and cleanVlppcontainers. Using movedVlppcontainers is not undefined behavior.
- The below rules only involve when
- When defining a
- When using other locks, try your best to only use methods that available to all platforms.
- Write cross platform code when it is performance optimal for all platforms.
- If Windows specific methods could make Windows implementation much better, then you are allowed to implement them in different ways.
- Use
lock(bothSpinLockandCriticalSection),mutex,semaphore,event,semaphore,rwlock,cvas lock variable prefixes.
- Prefer lock free construction only when the code would be simple, DO NOT involve complex lock free trick unless explicitly required.
std::atomic<T>should be considered and use it precisely. The code should be correct when running parallelly while I don't want unnecessarystd::atomic<T>.atomic_vintis widely used in the library, use it forvint.
- Avoid polling at all cost, I strongly prefer scheduling in async way.
Platform Independence
- Avoid using any platform specific methods.
ThreadPoolLite::Stopis an exception, if it is used in the application, this function is expected to call at the end ofmain.
Spawning Threads
vl::Thread class is for heavy resource and time consuming work work:
- Heave time consuming usually means the thread lasts for the lifecycle of the process.
- Inherit from
Threadand overrideRun. - Avoid using
CreateAndStartas your best effort, and strictly avoid in unit test projects, as there are small memory leaks that could pollute the memory leaks detecting.
vl::ThreadPoolLite class is for medium time consuming work:
- Medium time consuming usually means it is spawned to complete a task, and although the task takes time but it is expected to end.
- Avoid using this class too parallelly, it has a limited threads running at the background, queuing too many tasks would cause traffic.
RepeatingTaskExecutor queues inputs to trigger the same task when outdated input is discardable:
- Inherit from
RepeatingTaskExecutorand overrideExecute. - Calling
SubmitTaskcause the task to begin:- If the previous task is running, the new task would wait, otherwise it starts immediately.
- If the last submitted task did not start, it is discarded and replaced by the new one, aka the queue only stores one pending task.
- One submission executes the task once, when there is no task running, the system resource will be released.
- One example is editor auto completion with editing text as an input, if the user is typing too fast, outdated queued text is discardable because we only response to the last editor state.
TaskQueue queues multiple tasks to execute in a single thread:
RunTaskQueueblocks the thread forever untilQueueExitTaskis called. Before callingQueueExitTask, it blocks even when no task is running.QueueExitTaskdoes not cancel any pendingQueueTask, all queued task will be executed.
ThreadVariable<T> can be used on global variables, different threads see different copy even when using the same ThreadVariable<T> global variables.