1 /*
2 * cue-cache.cc
3 * Copyright 2016 John Lindgren
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions, and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions, and the following disclaimer in the documentation
13 * provided with the distribution.
14 *
15 * This software is provided "as is" and without any warranty, express or
16 * implied. In no event shall the authors be liable for any damages arising from
17 * the use of this software.
18 */
19
20 #include "cue-cache.h"
21 #include "multihash.h"
22 #include "playlist-internal.h"
23 #include "threads.h"
24
25 enum NodeState
26 {
27 NotLoaded,
28 Loading,
29 Loaded
30 };
31
32 struct CueCacheNode
33 {
34 Index<PlaylistAddItem> items;
35 NodeState state = NotLoaded;
36 int refcount = 0;
37 };
38
39 static SimpleHash<String, CueCacheNode> cache;
40 static aud::mutex mutex;
41 static aud::condvar cond;
42
CueCacheRef(const char * filename)43 CueCacheRef::CueCacheRef(const char * filename) : m_filename(filename)
44 {
45 auto mh = mutex.take();
46
47 m_node = cache.lookup(m_filename);
48 if (!m_node)
49 m_node = cache.add(m_filename, CueCacheNode());
50
51 m_node->refcount++;
52 }
53
~CueCacheRef()54 CueCacheRef::~CueCacheRef()
55 {
56 auto mh = mutex.take();
57
58 m_node->refcount--;
59 if (!m_node->refcount)
60 cache.remove(m_filename);
61 }
62
load()63 const Index<PlaylistAddItem> & CueCacheRef::load()
64 {
65 auto mh = mutex.take();
66 String title; // not used
67
68 switch (m_node->state)
69 {
70 case NotLoaded:
71 // load the cuesheet in this thread
72 m_node->state = Loading;
73 mh.unlock();
74 playlist_load(m_filename, title, m_node->items);
75 mh.lock();
76
77 m_node->state = Loaded;
78 cond.notify_all();
79 break;
80
81 case Loading:
82 // wait for cuesheet to load in another thread
83 while (m_node->state != Loaded)
84 cond.wait(mh);
85
86 break;
87
88 case Loaded:
89 // cuesheet already loaded
90 break;
91 }
92
93 return m_node->items;
94 }
95