summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/pool/test/TestPoolWork.c
diff options
context:
space:
mode:
Diffstat (limited to 'winpr/libwinpr/pool/test/TestPoolWork.c')
-rw-r--r--winpr/libwinpr/pool/test/TestPoolWork.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/winpr/libwinpr/pool/test/TestPoolWork.c b/winpr/libwinpr/pool/test/TestPoolWork.c
new file mode 100644
index 0000000..ec50a22
--- /dev/null
+++ b/winpr/libwinpr/pool/test/TestPoolWork.c
@@ -0,0 +1,136 @@
+
+#include <winpr/wtypes.h>
+#include <winpr/crt.h>
+#include <winpr/pool.h>
+#include <winpr/interlocked.h>
+
+static LONG count = 0;
+
+static void CALLBACK test_WorkCallback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work)
+{
+ printf("Hello %s: %03" PRId32 " (thread: 0x%08" PRIX32 ")\n", (char*)context,
+ InterlockedIncrement(&count), GetCurrentThreadId());
+
+ for (int index = 0; index < 100; index++)
+ {
+ BYTE a[1024];
+ BYTE b[1024];
+ BYTE c[1024] = { 0 };
+
+ FillMemory(a, ARRAYSIZE(a), 0xAA);
+ FillMemory(b, ARRAYSIZE(b), 0xBB);
+
+ CopyMemory(c, a, ARRAYSIZE(a));
+ CopyMemory(c, b, ARRAYSIZE(b));
+ }
+}
+
+static BOOL test1(void)
+{
+ PTP_WORK work = NULL;
+ printf("Global Thread Pool\n");
+ work = CreateThreadpoolWork(test_WorkCallback, "world", NULL);
+
+ if (!work)
+ {
+ printf("CreateThreadpoolWork failure\n");
+ return FALSE;
+ }
+
+ /**
+ * You can post a work object one or more times (up to MAXULONG) without waiting for prior
+ * callbacks to complete. The callbacks will execute in parallel. To improve efficiency, the
+ * thread pool may throttle the threads.
+ */
+
+ for (int index = 0; index < 10; index++)
+ SubmitThreadpoolWork(work);
+
+ WaitForThreadpoolWorkCallbacks(work, FALSE);
+ CloseThreadpoolWork(work);
+ return TRUE;
+}
+
+static BOOL test2(void)
+{
+ BOOL rc = FALSE;
+ PTP_POOL pool = NULL;
+ PTP_WORK work = NULL;
+ PTP_CLEANUP_GROUP cleanupGroup = NULL;
+ TP_CALLBACK_ENVIRON environment;
+ printf("Private Thread Pool\n");
+
+ if (!(pool = CreateThreadpool(NULL)))
+ {
+ printf("CreateThreadpool failure\n");
+ return FALSE;
+ }
+
+ if (!SetThreadpoolThreadMinimum(pool, 4))
+ {
+ printf("SetThreadpoolThreadMinimum failure\n");
+ goto fail;
+ }
+
+ SetThreadpoolThreadMaximum(pool, 8);
+ InitializeThreadpoolEnvironment(&environment);
+ SetThreadpoolCallbackPool(&environment, pool);
+ cleanupGroup = CreateThreadpoolCleanupGroup();
+
+ if (!cleanupGroup)
+ {
+ printf("CreateThreadpoolCleanupGroup failure\n");
+ goto fail;
+ }
+
+ SetThreadpoolCallbackCleanupGroup(&environment, cleanupGroup, NULL);
+ work = CreateThreadpoolWork(test_WorkCallback, "world", &environment);
+
+ if (!work)
+ {
+ printf("CreateThreadpoolWork failure\n");
+ goto fail;
+ }
+
+ for (int index = 0; index < 10; index++)
+ SubmitThreadpoolWork(work);
+
+ WaitForThreadpoolWorkCallbacks(work, FALSE);
+ rc = TRUE;
+fail:
+
+ if (cleanupGroup)
+ {
+ CloseThreadpoolCleanupGroupMembers(cleanupGroup, TRUE, NULL);
+ CloseThreadpoolCleanupGroup(cleanupGroup);
+ DestroyThreadpoolEnvironment(&environment);
+ /**
+ * See Remarks at
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx If there
+ * is a cleanup group associated with the work object, it is not necessary to call
+ * CloseThreadpoolWork ! calling the CloseThreadpoolCleanupGroupMembers function releases
+ * the work, wait, and timer objects associated with the cleanup group.
+ */
+#if 0
+ CloseThreadpoolWork(work); // this would segfault, see comment above. */
+#endif
+ }
+
+ CloseThreadpool(pool);
+ return rc;
+}
+
+int TestPoolWork(int argc, char* argv[])
+{
+
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+
+ if (!test1())
+ return -1;
+
+ if (!test2())
+ return -1;
+
+ return 0;
+}