From 37d2c8c06bce01f79b4cb74d9bc275f22f676750 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Thu, 24 Aug 2023 16:18:31 -0700 Subject: [PATCH] updates --- datastore.nimble | 1 + datastore/threadbackend.nim | 40 ++++++++++++++++++++++++++++--------- tests/exampletaskpool.nim | 34 +++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 tests/exampletaskpool.nim diff --git a/datastore.nimble b/datastore.nimble index 6252c6d..e14bb51 100644 --- a/datastore.nimble +++ b/datastore.nimble @@ -13,6 +13,7 @@ requires "nim >= 1.2.0", "sqlite3_abi", "stew", "unittest2", + "patty", "upraises >= 0.1.0 & < 0.2.0" task coverage, "generates code coverage report": diff --git a/datastore/threadbackend.nim b/datastore/threadbackend.nim index 57a245d..27fe9c3 100644 --- a/datastore/threadbackend.nim +++ b/datastore/threadbackend.nim @@ -4,6 +4,8 @@ import pkg/chronos import pkg/questionable import pkg/questionable/results import pkg/upraises +import pkg/taskpools +import pkg/patty import ./key import ./query @@ -14,9 +16,29 @@ export key, query push: {.upraises: [].} +variant Shape: + Circle(r: float) + Rectangle(w: float, h: float) + type + DatastoreBackend* {.pure.} = enum + FileSystem + SQlite + ThreadDatastore* = ref object of Datastore - # stores*: Table[KeyBuffer, ThreadDatastore] + tp: Taskpool + +var backendDatastore {.threadvar.}: ref Datastore + +proc startupDatastore(backend: DatastoreBackend): bool = + + case backend: + of FileSystem: + backendDatastore = FSDatastore.new( + root: string, + depth = 2, + caseSensitive = true, + ignoreProtected = false proc has*( self: ThreadDatastore, @@ -86,20 +108,20 @@ proc put*( proc close*( self: ThreadDatastore ): Future[?!void] {.async.} = - - # for s in self.stores.values: - # discard await s.store.close() - - # TODO: how to handle failed close? + self.tp.shutdown() return success() func new*[S: ref Datastore]( T: typedesc[ThreadDatastore], - storeTp: typedesc[S] + backend: DatastoreBackend, ): ?!ThreadDatastore = var self = T() - # for (k, v) in stores.pairs: - # self.stores[?k.path] = MountedStore(store: v, key: k) + self.tp = Taskpool.new(num_threads = 1) ##\ + ## Default to one thread, multiple threads \ + ## will require more work + + let pending = self.tp.spawn startupDatastore(backend) + sync pending success self diff --git a/tests/exampletaskpool.nim b/tests/exampletaskpool.nim new file mode 100644 index 0000000..c410235 --- /dev/null +++ b/tests/exampletaskpool.nim @@ -0,0 +1,34 @@ + + +import + std/[strutils, math, cpuinfo], + taskpools + +# From https://github.com/nim-lang/Nim/blob/v1.6.2/tests/parallel/tpi.nim +# Leibniz Formula https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80 +proc term(k: int): float = + if k mod 2 == 1: + -4'f / float(2*k + 1) + else: + 4'f / float(2*k + 1) + +proc piApprox(tp: Taskpool, n: int): float = + var pendingFuts = newSeq[FlowVar[float]](n) + for k in 0 ..< pendingFuts.len: + pendingFuts[k] = tp.spawn term(k) # Schedule a task on the threadpool a return a handle to retrieve the result. + for k in 0 ..< pendingFuts.len: + result += sync pendingFuts[k] # Block until the result is available. + +proc main() = + var n = 1_000_000 + var nthreads = countProcessors() + + var tp = Taskpool.new(num_threads = nthreads) # Default to the number of hardware threads. + + echo formatFloat(tp.piApprox(n)) + + tp.syncAll() # Block until all pending tasks are processed (implied in tp.shutdown()) + tp.shutdown() + +# Compile with nim c -r -d:release --threads:on --outdir:build example.nim +main() \ No newline at end of file