Common System 0.2.0
Common interfaces and patterns for system integration
Loading...
Searching...
No Matches
executor_example.cpp File Reference
#include <kcenon/common/interfaces/executor_interface.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <atomic>
#include <queue>
#include <mutex>
#include <condition_variable>
Include dependency graph for executor_example.cpp:

Go to the source code of this file.

Classes

class  mock_executor
 
class  function_job
 
class  calculation_job
 
class  example_executor_provider
 

Functions

void process_data_batch (IExecutor &executor, const std::vector< int > &data)
 
int main ()
 

Function Documentation

◆ main()

int main ( )

Definition at line 299 of file executor_example.cpp.

299 {
300 std::cout << "=== IExecutor Interface Examples ===\n\n";
301
302 // Example 1: Basic usage
303 std::cout << "1. Basic task execution:\n";
304 mock_executor executor(2);
305
306 auto job1 = std::make_unique<function_job>([] {
307 std::cout << " Task 1 executed\n";
308 });
309 auto result1 = executor.execute(std::move(job1));
310 if (result1.is_ok()) {
311 std::move(result1).value().wait();
312 }
313
314 auto job2 = std::make_unique<function_job>([] {
315 std::cout << " Task 2 executed\n";
316 });
317 auto result2 = executor.execute(std::move(job2));
318 if (result2.is_ok()) {
319 std::move(result2).value().wait();
320 }
321
322 // Example 2: Check executor status
323 std::cout << "\n2. Executor status:\n";
324 std::cout << " Workers: " << executor.worker_count() << "\n";
325 std::cout << " Running: " << (executor.is_running() ? "yes" : "no") << "\n";
326 std::cout << " Pending: " << executor.pending_tasks() << "\n";
327
328 // Example 3: Batch processing
329 std::cout << "\n3. Batch processing:\n";
330 std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
331 process_data_batch(executor, data);
332
333 // Example 4: Using executor provider
334 std::cout << "\n4. Using executor provider:\n";
336 auto shared_executor = provider.get_executor();
337
338 auto provider_job = std::make_unique<function_job>([] {
339 std::cout << " Task from shared executor\n";
340 });
341 auto provider_result = shared_executor->execute(std::move(provider_job));
342 if (provider_result.is_ok()) {
343 std::move(provider_result).value().wait();
344 }
345
346 // Example 5: Delayed execution
347 std::cout << "\n5. Delayed execution:\n";
348 std::cout << " Scheduling delayed task...\n";
349 auto start = std::chrono::steady_clock::now();
350
351 auto delayed_job = std::make_unique<function_job>([start] {
352 auto elapsed = std::chrono::steady_clock::now() - start;
353 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);
354 std::cout << " Delayed task executed after " << ms.count() << "ms\n";
355 });
356
357 auto delayed_result = executor.execute_delayed(std::move(delayed_job), 500ms);
358 if (delayed_result.is_ok()) {
359 std::move(delayed_result).value().wait();
360 }
361
362 // Example 6: Error handling
363 std::cout << "\n6. Error handling:\n";
364 auto error_job = std::make_unique<function_job>([] {
365 throw std::runtime_error("Task failed!");
366 });
367
368 auto error_result = executor.execute(std::move(error_job));
369 if (error_result.is_ok()) {
370 try {
371 auto error_future = std::move(error_result.value());
372 error_future.get();
373 } catch (const std::exception& e) {
374 std::cout << " Caught exception: " << e.what() << "\n";
375 }
376 }
377
378 // Example 7: Custom job execution
379 std::cout << "\n7. Custom job execution:\n";
380 {
381 mock_executor job_executor(2);
382 std::atomic<int> job_sum{0};
383 std::vector<std::future<void>> job_futures;
384
385 std::cout << " Executing calculation jobs...\n";
386 for (int i = 1; i <= 5; ++i) {
387 auto job = std::make_unique<calculation_job>(i, job_sum);
388 auto result = job_executor.execute(std::move(job));
389
390 if (result.is_ok()) {
391 job_futures.push_back(std::move(result.value()));
392 } else {
393 const auto& err = result.error();
394 std::cout << " Failed to execute job: "
395 << err.message << "\n";
396 }
397 }
398
399 // Wait for all jobs to complete
400 for (auto& future : job_futures) {
401 future.wait();
402 }
403
404 std::cout << " Custom job sum of squares: " << job_sum << "\n";
405 }
406
407 // Example 8: Graceful shutdown
408 std::cout << "\n8. Graceful shutdown:\n";
409
410 // Execute some tasks
411 for (int i = 0; i < 5; ++i) {
412 auto final_job = std::make_unique<function_job>([i] {
413 std::this_thread::sleep_for(50ms);
414 std::cout << " Final task " << i << " completed\n";
415 });
416 executor.execute(std::move(final_job));
417 }
418
419 std::cout << " Pending tasks before shutdown: "
420 << executor.pending_tasks() << "\n";
421 std::cout << " Shutting down (waiting for completion)...\n";
422
423 executor.shutdown(true);
424 std::cout << " Shutdown complete\n";
425
426 std::cout << "\n=== Examples completed ===\n";
427 return 0;
428}
std::shared_ptr< IExecutor > get_executor() override
Get the default executor instance.
const error_info & error() const
Get error reference.
Definition core.h:405
void process_data_batch(IExecutor &executor, const std::vector< int > &data)
VoidResult err(const error_info &error)
Factory function to create error VoidResult.
Definition core.cppm:432

References kcenon::common::err(), kcenon::common::Result< T >::error(), mock_executor::execute(), mock_executor::execute_delayed(), example_executor_provider::get_executor(), mock_executor::is_running(), mock_executor::pending_tasks(), process_data_batch(), mock_executor::shutdown(), and mock_executor::worker_count().

Here is the call graph for this function:

◆ process_data_batch()

void process_data_batch ( IExecutor & executor,
const std::vector< int > & data )

Example function that uses IExecutor interface

Examples
executor_example.cpp.

Definition at line 250 of file executor_example.cpp.

250 {
251 std::atomic<int> sum{0};
252 std::vector<std::future<void>> futures;
253
254 std::cout << "Processing " << data.size() << " items using "
255 << executor.worker_count() << " workers\n";
256
257 // Submit tasks using job-based API
258 for (int value : data) {
259 auto job = std::make_unique<function_job>([&sum, value] {
260 // Simulate some work
261 std::this_thread::sleep_for(10ms);
262 sum += value * value;
263 });
264
265 auto result = executor.execute(std::move(job));
266 if (result.is_ok()) {
267 futures.push_back(std::move(result.value()));
268 }
269 }
270
271 // Wait for completion
272 for (auto& future : futures) {
273 future.wait();
274 }
275
276 std::cout << "Sum of squares: " << sum << "\n";
277}
virtual size_t worker_count() const =0
Get the number of worker threads.
virtual Result< std::future< void > > execute(std::unique_ptr< IJob > &&job)=0
Execute a job with Result-based error handling.

References kcenon::common::interfaces::IExecutor::execute(), and kcenon::common::interfaces::IExecutor::worker_count().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function: