299 {
300 std::cout << "=== IExecutor Interface Examples ===\n\n";
301
302
303 std::cout << "1. Basic task execution:\n";
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
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
329 std::cout << "\n3. Batch processing:\n";
330 std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
332
333
334 std::cout << "\n4. Using executor provider:\n";
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
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
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
379 std::cout << "\n7. Custom job execution:\n";
380 {
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 {
394 std::cout << " Failed to execute job: "
395 <<
err.message <<
"\n";
396 }
397 }
398
399
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
408 std::cout << "\n8. Graceful shutdown:\n";
409
410
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.
void process_data_batch(IExecutor &executor, const std::vector< int > &data)
VoidResult err(const error_info &error)
Factory function to create error VoidResult.