|
| 1 | +#include <algorithm> |
| 2 | +#include <chrono> |
| 3 | +#include <iostream> |
| 4 | +#include <mutex> |
| 5 | +#include <thread> |
| 6 | +#include <vector> |
| 7 | +#include "../../src/foundation/id_allocator.h" |
| 8 | + |
| 9 | +using namespace nativeapi; |
| 10 | + |
| 11 | +// Define some example types for demonstration |
| 12 | +struct Window {}; |
| 13 | +struct Menu {}; |
| 14 | +struct MenuItem {}; |
| 15 | +struct TrayIcon {}; |
| 16 | +struct Display {}; |
| 17 | + |
| 18 | +int main() { |
| 19 | + std::cout << "IdAllocator Template Example" << std::endl; |
| 20 | + std::cout << "============================" << std::endl; |
| 21 | + |
| 22 | + // Example 1: Basic allocation for different object types |
| 23 | + std::cout << "\n1. Basic Allocation:" << std::endl; |
| 24 | + |
| 25 | + auto window_id = IdAllocator::Allocate<Window>(); |
| 26 | + auto menu_id = IdAllocator::Allocate<Menu>(); |
| 27 | + auto tray_id = IdAllocator::Allocate<TrayIcon>(); |
| 28 | + |
| 29 | + std::cout << "Window ID: 0x" << std::hex << window_id << std::dec |
| 30 | + << " (Type: " << IdAllocator::GetType(window_id) |
| 31 | + << ", Sequence: " << IdAllocator::GetSequence(window_id) << ")" |
| 32 | + << std::endl; |
| 33 | + |
| 34 | + std::cout << "Menu ID: 0x" << std::hex << menu_id << std::dec |
| 35 | + << " (Type: " << IdAllocator::GetType(menu_id) |
| 36 | + << ", Sequence: " << IdAllocator::GetSequence(menu_id) << ")" |
| 37 | + << std::endl; |
| 38 | + |
| 39 | + std::cout << "Tray ID: 0x" << std::hex << tray_id << std::dec |
| 40 | + << " (Type: " << IdAllocator::GetType(tray_id) |
| 41 | + << ", Sequence: " << IdAllocator::GetSequence(tray_id) << ")" |
| 42 | + << std::endl; |
| 43 | + |
| 44 | + // Example 2: TryAllocate with error checking |
| 45 | + std::cout << "\n2. TryAllocate (safer allocation):" << std::endl; |
| 46 | + |
| 47 | + auto maybe_id = IdAllocator::TryAllocate<MenuItem>(); |
| 48 | + if (maybe_id != IdAllocator::kInvalidId) { |
| 49 | + std::cout << "MenuItem ID allocated successfully: 0x" << std::hex |
| 50 | + << maybe_id << std::dec << std::endl; |
| 51 | + } else { |
| 52 | + std::cout << "MenuItem ID allocation failed" << std::endl; |
| 53 | + } |
| 54 | + |
| 55 | + // Example 3: ID validation and decomposition |
| 56 | + std::cout << "\n3. ID Validation and Decomposition:" << std::endl; |
| 57 | + |
| 58 | + std::cout << "Is window_id valid? " |
| 59 | + << (IdAllocator::IsValid(window_id) ? "Yes" : "No") << std::endl; |
| 60 | + |
| 61 | + auto decomposed = IdAllocator::Decompose(window_id); |
| 62 | + std::cout << "Window ID decomposed - Type: " << decomposed.first |
| 63 | + << ", Sequence: " << decomposed.second << std::endl; |
| 64 | + |
| 65 | + // Example 4: Current count query |
| 66 | + std::cout << "\n4. Current Counter Query:" << std::endl; |
| 67 | + |
| 68 | + std::cout << "Current Window counter (before allocation): " |
| 69 | + << IdAllocator::GetCurrentCount<Window>() << std::endl; |
| 70 | + |
| 71 | + auto new_window_id = IdAllocator::Allocate<Window>(); |
| 72 | + std::cout << "New Window ID: 0x" << std::hex << new_window_id << std::dec |
| 73 | + << " (Sequence: " << IdAllocator::GetSequence(new_window_id) << ")" |
| 74 | + << std::endl; |
| 75 | + |
| 76 | + std::cout << "Current Window counter (after allocation): " |
| 77 | + << IdAllocator::GetCurrentCount<Window>() << std::endl; |
| 78 | + |
| 79 | + // Example 5: Multiple allocations |
| 80 | + std::cout << "\n5. Multiple Allocations:" << std::endl; |
| 81 | + |
| 82 | + std::vector<IdAllocator::IdType> window_ids; |
| 83 | + for (int i = 0; i < 5; ++i) { |
| 84 | + window_ids.push_back(IdAllocator::Allocate<Window>()); |
| 85 | + } |
| 86 | + |
| 87 | + std::cout << "Allocated " << window_ids.size() << " Window IDs:" << std::endl; |
| 88 | + for (size_t i = 0; i < window_ids.size(); ++i) { |
| 89 | + std::cout << " ID " << (i + 1) << ": 0x" << std::hex << window_ids[i] |
| 90 | + << std::dec |
| 91 | + << " (Sequence: " << IdAllocator::GetSequence(window_ids[i]) |
| 92 | + << ")" << std::endl; |
| 93 | + } |
| 94 | + |
| 95 | + // Example 6: Thread safety demonstration |
| 96 | + std::cout << "\n6. Thread Safety Demonstration:" << std::endl; |
| 97 | + |
| 98 | + std::vector<std::thread> threads; |
| 99 | + std::vector<IdAllocator::IdType> thread_ids; |
| 100 | + std::mutex ids_mutex; |
| 101 | + |
| 102 | + const int num_threads = 3; |
| 103 | + const int ids_per_thread = 10; |
| 104 | + |
| 105 | + auto start_time = std::chrono::high_resolution_clock::now(); |
| 106 | + |
| 107 | + for (int i = 0; i < num_threads; ++i) { |
| 108 | + threads.emplace_back([&thread_ids, &ids_mutex, ids_per_thread, i]() { |
| 109 | + std::vector<IdAllocator::IdType> local_ids; |
| 110 | + |
| 111 | + for (int j = 0; j < ids_per_thread; ++j) { |
| 112 | + auto id = IdAllocator::Allocate<Display>(); |
| 113 | + local_ids.push_back(id); |
| 114 | + } |
| 115 | + |
| 116 | + { |
| 117 | + std::lock_guard<std::mutex> lock(ids_mutex); |
| 118 | + thread_ids.insert(thread_ids.end(), local_ids.begin(), local_ids.end()); |
| 119 | + } |
| 120 | + }); |
| 121 | + } |
| 122 | + |
| 123 | + for (auto& thread : threads) { |
| 124 | + thread.join(); |
| 125 | + } |
| 126 | + |
| 127 | + auto end_time = std::chrono::high_resolution_clock::now(); |
| 128 | + auto duration = std::chrono::duration_cast<std::chrono::microseconds>( |
| 129 | + end_time - start_time); |
| 130 | + |
| 131 | + std::cout << "Allocated " << thread_ids.size() << " Display IDs from " |
| 132 | + << num_threads << " threads in " << duration.count() |
| 133 | + << " microseconds" << std::endl; |
| 134 | + |
| 135 | + // Verify all IDs are unique |
| 136 | + std::sort(thread_ids.begin(), thread_ids.end()); |
| 137 | + auto it = std::unique(thread_ids.begin(), thread_ids.end()); |
| 138 | + std::cout << "All IDs are unique: " << (it == thread_ids.end() ? "Yes" : "No") |
| 139 | + << std::endl; |
| 140 | + |
| 141 | + // Example 7: Different object types |
| 142 | + std::cout << "\n7. Different Object Types:" << std::endl; |
| 143 | + |
| 144 | + auto display_id = IdAllocator::Allocate<Display>(); |
| 145 | + |
| 146 | + std::cout << "Display ID: 0x" << std::hex << display_id << std::dec |
| 147 | + << " (Type: " << IdAllocator::GetType(display_id) << ")" |
| 148 | + << std::endl; |
| 149 | + |
| 150 | + // Example 8: Reset functionality (for testing) |
| 151 | + std::cout << "\n8. Reset Functionality:" << std::endl; |
| 152 | + |
| 153 | + std::cout << "Menu counter before reset: " |
| 154 | + << IdAllocator::GetCurrentCount<Menu>() << std::endl; |
| 155 | + IdAllocator::Reset<Menu>(); |
| 156 | + std::cout << "Menu counter after reset: " |
| 157 | + << IdAllocator::GetCurrentCount<Menu>() << std::endl; |
| 158 | + |
| 159 | + auto new_menu_id = IdAllocator::Allocate<Menu>(); |
| 160 | + std::cout << "New Menu ID after reset: 0x" << std::hex << new_menu_id |
| 161 | + << std::dec |
| 162 | + << " (Sequence: " << IdAllocator::GetSequence(new_menu_id) << ")" |
| 163 | + << std::endl; |
| 164 | + |
| 165 | + // Example 9: Independent types after reset |
| 166 | + std::cout << "\n9. Independent Types After Reset:" << std::endl; |
| 167 | + |
| 168 | + auto window_after_reset = IdAllocator::Allocate<Window>(); |
| 169 | + std::cout << "Window ID after Menu reset: 0x" << std::hex |
| 170 | + << window_after_reset << std::dec |
| 171 | + << " (Sequence: " << IdAllocator::GetSequence(window_after_reset) |
| 172 | + << ")" << std::endl; |
| 173 | + std::cout << "Window counter was not affected by Menu reset" << std::endl; |
| 174 | + |
| 175 | + std::cout << "\nExample completed successfully!" << std::endl; |
| 176 | + return 0; |
| 177 | +} |
0 commit comments