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