1/*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef AVSHAREDMEMORYPOOL_H
17#define AVSHAREDMEMORYPOOL_H
18
19#include <condition_variable>
20#include <functional>
21#include <list>
22#include <memory>
23#include <mutex>
24#include "nocopyable.h"
25#include "buffer/avsharedmemorybase.h"
26
27namespace OHOS {
28namespace Media {
29/**
30 * @brief A simple pool implementation for shared memory.
31 *
32 * This pool support multi configuration:
33 * @preAllocMemCnt: The number of memory blocks allocated when the pool is initialized.
34 * @memSize: the size of the preallocated memory blocks.
35 * @maxMemCnt: the total number of memory blocks in the pool.
36 * @flags: the shared memory access property, refer to {@AVSharedMemory::Flags}.
37 * @enableFixedSize: if true, the pool will allocate all memory block using the memSize. If the acquired
38 *                  size is larger than the memSize, the acquire will failed. If false, the pool will
39 *                  free the smallest idle memory block when there is no idle memory block that can
40 *                  satisfy the acqiured size and reallocate a new memory block with the acquired size.
41 * @notifier: the callback will be called to notify there are any available memory. It will be useful for
42 *            non-blocking memory acquisition.
43 */
44class AVSharedMemoryPool : public std::enable_shared_from_this<AVSharedMemoryPool>, public NoCopyable {
45public:
46    explicit AVSharedMemoryPool(const std::string &name);
47    ~AVSharedMemoryPool();
48
49    using MemoryAvailableNotifier = std::function<void(void)>;
50
51    struct InitializeOption {
52        uint32_t preAllocMemCnt = 0;
53        int32_t memSize = 0;
54        uint32_t maxMemCnt = 0;
55        uint32_t flags = AVSharedMemory::Flags::FLAGS_READ_WRITE;
56        bool enableFixedSize = true;
57        MemoryAvailableNotifier notifier;
58    };
59
60    /**
61     * @brief Initialize the pool and preallocate some memory blocks.
62     */
63    int32_t Init(const InitializeOption &option);
64
65    /**
66     * @brief Get a memory from the pool and optional to wait for a memory to be release when there
67     * are no memories available.
68     *
69     * @param size the expected memory size. if the enableFixedSize is configured, this param can be empty.
70     * @return valid memory block if success, or nullptr.
71     */
72    std::shared_ptr<AVSharedMemory> AcquireMemory(int32_t size = -1, bool blocking = true);
73
74    /**
75     * @brief Set or Unset the pool to be non-blocking memory pool. If enable, the AcquireMemory will always
76     * be non-blocking and the waiters will be returned with null memory.
77     */
78    void SetNonBlocking(bool enable);
79
80    /**
81     * @brief Free all memory blocks and reset the pool configuration. After reseted, all waiters of
82     * the pool will be awaken up and returned with a nullptr.
83     */
84    void Reset();
85
86    std::string GetName()
87    {
88        return name_;
89    }
90
91private:
92    bool DoAcquireMemory(int32_t size, AVSharedMemory **outMemory);
93    AVSharedMemory *AllocMemory(int32_t size);
94    void ReleaseMemory(AVSharedMemory *memory);
95    bool CheckSize(int32_t size);
96
97    InitializeOption option_ {};
98    std::list<AVSharedMemory *> idleList_;
99    std::list<AVSharedMemory *> busyList_;
100    std::mutex mutex_;
101    std::condition_variable cond_;
102    bool inited_ = false;
103    std::string name_;
104    MemoryAvailableNotifier notifier_;
105    bool forceNonBlocking_ = false;
106};
107} // namespace Media
108} // namespace OHOS
109
110#endif