1 /******************************************************************************* 2 3 Test for AsyncIO. 4 5 Copyright: 6 Copyright (c) 2018 dunnhumby Germany GmbH. 7 All rights reserved. 8 9 License: 10 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 11 Alternatively, this file may be distributed under the terms of the Tango 12 3-Clause BSD License (see LICENSE_BSD.txt for details). 13 14 *******************************************************************************/ 15 16 module integrationtest.asyncio.main; 17 18 import ocean.meta.types.Qualifiers; 19 20 import core.sys.posix.sys.stat; 21 import core.sys.posix.pthread; 22 import core.thread : pthread_getattr_np; 23 import ocean.core.Test; 24 import ocean.sys.ErrnoException; 25 import ocean.util.app.DaemonApp; 26 import ocean.task.Scheduler; 27 import ocean.task.Task; 28 import ocean.util.aio.AsyncIO; 29 import ocean.io.device.File; 30 import ocean.util.test.DirectorySandbox; 31 32 class AsyncIOUsingApp: DaemonApp 33 { 34 AsyncIO async_io; 35 36 this ( ) 37 { 38 39 string name = "Application"; 40 string desc = "Testing async IO"; 41 42 DaemonApp.OptionalSettings settings; 43 settings.use_task_ext = true; 44 45 super(name, desc, VersionInfo.init, settings); 46 } 47 48 49 /// Per-thread context to be used by the delegate 50 class AioContext: AsyncIO.Context 51 { 52 void* thread_sp; 53 } 54 55 /// Delegate to call once per thread to create and 56 /// initialize the thread context. Normally used 57 /// to initialize libraries needed for the callback 58 /// delegates 59 AsyncIO.Context makeContext() 60 { 61 auto ctx = new AioContext; 62 63 pthread_attr_t attr; 64 void* stack_addr; 65 size_t stack_size; 66 67 pthread_getattr_np(pthread_self(), &attr); 68 pthread_attr_getstack(&attr, &stack_addr, &stack_size); 69 pthread_attr_destroy(&attr); 70 71 ctx.thread_sp = stack_addr; 72 73 return ctx; 74 } 75 76 /// counter value to set from the working thread 77 int counter; 78 79 /// last thread's sp value 80 void* thread_sp; 81 82 /// Callback called from another thread to set the counter 83 private void setCounter (AsyncIO.Context ctx) 84 { 85 auto myctx = cast(AioContext)ctx; 86 87 this.thread_sp = myctx.thread_sp; 88 this.counter++; 89 } 90 91 // Called after arguments and config file parsing. 92 override protected int run ( Arguments args, ConfigParser config ) 93 { 94 this.async_io = new AsyncIO(theScheduler.epoll, 10, &makeContext); 95 96 // open a new file 97 auto f = new File("var/output.txt", File.ReadWriteAppending); 98 99 char[] buf = "Hello darkness, my old friend.".dup; 100 this.async_io.blocking.write(buf, f.fileHandle()); 101 102 buf[] = '\0'; 103 this.async_io.blocking.pread(buf, f.fileHandle(), 0); 104 105 test!("==")(buf[], "Hello darkness, my old friend."); 106 test!("==")(f.length, buf.length); 107 108 this.async_io.blocking.callDelegate(&setCounter); 109 test!("==")(this.counter, 1); 110 test!("!is")(this.thread_sp, null); 111 112 theScheduler.shutdown(); 113 return 0; // return code to OS 114 } 115 } 116 117 version (unittest) {} else 118 void main(string[] args) 119 { 120 121 initScheduler(SchedulerConfiguration.init); 122 theScheduler.exception_handler = (Task t, Exception e) { 123 throw e; 124 }; 125 126 auto sandbox = DirectorySandbox.create(["etc", "log", "var"]); 127 128 File.set("etc/config.ini", "[LOG.Root]\n" ~ 129 "console = false\n\n"); 130 131 auto app = new AsyncIOUsingApp; 132 auto ret = app.main(args); 133 }