2 * Copyright 2013 Sveriges Television AB http://casparcg.com/
4 * This file is part of CasparCG (www.casparcg.com).
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
19 * Author: Helge Norberg, helge.norberg@svt.se
30 #include <boost/thread.hpp>
32 #include <tbb/concurrent_queue.h>
33 #include <tbb/concurrent_unordered_map.h>
34 #include <tbb/atomic.h>
36 #include <common/utility/assert.h>
37 //#include <common/memory/page_locked_allocator.h>
38 #include <common/exception/win32_exception.h>
40 #include "../interop/DeckLinkAPI_h.h"
42 namespace caspar { namespace decklink {
44 class thread_safe_decklink_allocator : public IDeckLinkMemoryAllocator
46 typedef std::shared_ptr<
47 std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>>> buffer;
50 tbb::concurrent_unordered_map<size_t, tbb::concurrent_queue<void*>> free_;
51 tbb::concurrent_unordered_map<void*, buffer> buffers_;
52 tbb::atomic<size_t> total_allocated_;
53 tbb::atomic<int64_t> total_calls_;
55 thread_safe_decklink_allocator(const std::wstring& print)
62 ~thread_safe_decklink_allocator()
66 << L" allocated a total of " << total_allocated_ << L" bytes"
67 << L" and was called " << total_calls_ << L" times"
68 << L" during playout";
71 virtual HRESULT STDMETHODCALLTYPE AllocateBuffer(
72 unsigned long buffer_size, void** allocated_buffer)
74 win32_exception::ensure_handler_installed_for_thread(
75 "decklink-allocator");
79 *allocated_buffer = allocate_buffer(buffer_size);
81 catch (const std::bad_alloc&)
83 CASPAR_LOG_CURRENT_EXCEPTION();
91 void* allocate_buffer(unsigned long buffer_size)
96 if (!free_[buffer_size].try_pop(result))
98 auto buf = std::make_shared<std::vector<uint8_t,
99 tbb::cache_aligned_allocator<uint8_t>>>(buffer_size);
100 result = buf->data();
101 buffers_.insert(std::make_pair(result, buf));
103 total_allocated_ += buffer_size;
107 << L" allocated buffer of size: " << buffer_size
108 << L" for a total of " << total_allocated_;
114 virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer(void* b)
116 win32_exception::ensure_handler_installed_for_thread(
117 "decklink-allocator");
123 catch (const std::bad_alloc&)
125 CASPAR_LOG_CURRENT_EXCEPTION();
131 void release_buffer(void* b)
133 auto buf = buffers_[b];
137 free_[buf->size()].push(b);
140 virtual HRESULT STDMETHODCALLTYPE Commit()
145 virtual HRESULT STDMETHODCALLTYPE Decommit()
150 STDMETHOD (QueryInterface(REFIID, LPVOID*)) {return E_NOINTERFACE;}
151 STDMETHOD_(ULONG, AddRef()) {return 1;}
152 STDMETHOD_(ULONG, Release()) {return 1;}