@@ -341,6 +341,112 @@ template <> void llama_file_buffer<true>::write_u32(uint32_t val) const {
341
341
template struct llama_file_buffer <false >;
342
342
template struct llama_file_buffer <true >;
343
343
344
+ // llama_future_file_buffer implementation
345
+
346
+ namespace {
347
+ std::string final_key (const std::string & promise_key, const std::string & context) {
348
+ return promise_key + " :" + context;
349
+ }
350
+
351
+ std::mutex promise_registry_mutex;
352
+
353
+ std::map<std::string, std::promise<std::unique_ptr<llama_file_buffer<false >>>> promise_registry_ro;
354
+ std::map<std::string, std::promise<std::unique_ptr<llama_file_buffer<true >>>> promise_registry_rw;
355
+
356
+ template <bool Writable>
357
+ std::map<std::string, std::promise<std::unique_ptr<llama_file_buffer<Writable>>>> & promise_registry () {
358
+ if constexpr (Writable) {
359
+ return promise_registry_rw;
360
+ } else {
361
+ return promise_registry_ro;
362
+ }
363
+ }
364
+
365
+ // / @brief Ensures a promise exists in the registry for the given key.
366
+ // / If it doesn't exist, creates it. Returns an iterator to the promise.
367
+ // / Thread-safe.
368
+ template <bool Writable>
369
+ typename std::map<std::string, std::promise<std::unique_ptr<llama_file_buffer<Writable>>>>::iterator
370
+ ensure_promise_registry (const std::string & key) {
371
+ std::lock_guard<std::mutex> lock (promise_registry_mutex);
372
+ auto it = promise_registry<Writable>().find (key);
373
+ if (it != promise_registry<Writable>().end ()) {
374
+ return it;
375
+ }
376
+ auto result =
377
+ promise_registry<Writable>().emplace (key, std::promise<std::unique_ptr<llama_file_buffer<Writable>>>());
378
+ LLAMA_LOG_CMAKE_DEBUG (" %s: created future file buffer %p for %s\n " , __func__, (void *) &(*it), key.c_str ());
379
+ return result.first ;
380
+ }
381
+ } // namespace
382
+
383
+ template <bool Writable>
384
+ llama_future_file_buffer<Writable>::llama_future_file_buffer(const std::string & promise_key,
385
+ const std::string & context) :
386
+ file_buffer_future (),
387
+ file_buffer() {
388
+ std::string key = final_key (promise_key, context);
389
+ file_buffer_promise_iterator = ensure_promise_registry<Writable>(key);
390
+ file_buffer_future = file_buffer_promise_iterator->second .get_future ();
391
+ }
392
+
393
+ template <bool Writable>
394
+ llama_future_file_buffer<Writable>::llama_future_file_buffer(llama_future_file_buffer && other) noexcept :
395
+ file_buffer_promise_iterator (std::move(other.file_buffer_promise_iterator)),
396
+ file_buffer_future(std::move(other.file_buffer_future)),
397
+ file_buffer(std::move(other.file_buffer)) {
398
+ // Set the other object's iterator to end() to mark it as moved from
399
+ // to avoid early erasure at destruction of the moved other object
400
+ other.file_buffer_promise_iterator = promise_registry<Writable>().end ();
401
+ }
402
+
403
+ template <bool Writable>
404
+ llama_future_file_buffer<Writable> & llama_future_file_buffer<Writable>::operator =(
405
+ llama_future_file_buffer && other) noexcept {
406
+ if (this != &other) {
407
+ file_buffer_promise_iterator = std::move (other.file_buffer_promise_iterator );
408
+ file_buffer_future = std::move (other.file_buffer_future );
409
+ file_buffer = std::move (other.file_buffer );
410
+ other.file_buffer_promise_iterator = promise_registry<Writable>().end ();
411
+ }
412
+ return *this ;
413
+ }
414
+
415
+ template <bool Writable> llama_future_file_buffer<Writable>::~llama_future_file_buffer () {
416
+ std::lock_guard<std::mutex> lock (promise_registry_mutex);
417
+ if (file_buffer_promise_iterator != promise_registry<Writable>().end ()) {
418
+ promise_registry<Writable>().erase (file_buffer_promise_iterator);
419
+ }
420
+ }
421
+
422
+ template <bool Writable>
423
+ bool llama_future_file_buffer<Writable>::fulfill_promise(const std::string & promise_key, const std::string & context,
424
+ std::unique_ptr<llama_file_buffer<Writable>> && value) {
425
+ std::string key = final_key (promise_key, context);
426
+ auto it = ensure_promise_registry<Writable>(key);
427
+ if (it != promise_registry<Writable>().end ()) {
428
+ LLAMA_LOG_CMAKE_DEBUG (" fulfilling future file buffer %p for %s\n " , (void *) &(*it), key.c_str ());
429
+ it->second .set_value (std::move (value));
430
+ return true ;
431
+ }
432
+ return false ;
433
+ }
434
+
435
+ template <bool Writable>
436
+ std::unique_ptr<llama_file_buffer<Writable>> llama_future_file_buffer<Writable>::extract() const {
437
+ if (file_buffer) {
438
+ return std::move (file_buffer);
439
+ }
440
+
441
+ auto future_result = file_buffer_future.get ();
442
+ file_buffer = std::move (future_result);
443
+ return std::move (file_buffer);
444
+ }
445
+
446
+ // Explicit instantiations for llama_future_file_buffer
447
+ template struct llama_future_file_buffer <false >;
448
+ template struct llama_future_file_buffer <true >;
449
+
344
450
// llama_mmap
345
451
346
452
struct llama_mmap ::impl {
0 commit comments