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