Changes in / [3b402339:144fa5c]
- Files:
-
- 3 deleted
- 11 edited
-
benchmark/io/http/http_ring.cpp (modified) (16 diffs)
-
benchmark/io/http/parhttperf (deleted)
-
benchmark/io/http/parse-httperf.py (deleted)
-
doc/theses/andrew_beach_MMath/existing.tex (modified) (1 diff)
-
doc/theses/andrew_beach_MMath/features.tex (modified) (12 diffs)
-
doc/theses/andrew_beach_MMath/implement.tex (modified) (1 diff)
-
doc/theses/andrew_beach_MMath/thesis-frontpgs.tex (modified) (7 diffs)
-
doc/theses/andrew_beach_MMath/thesis.tex (modified) (5 diffs)
-
doc/theses/andrew_beach_MMath/uw-ethesis-frontpgs.tex (modified) (6 diffs)
-
doc/theses/andrew_beach_MMath/uw-ethesis.tex (modified) (11 diffs)
-
libcfa/src/memory.cfa (modified) (4 diffs)
-
libcfa/src/memory.hfa (modified) (2 diffs)
-
tests/.expect/smart-pointers.txt (deleted)
-
tests/smart-pointers.cfa (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
benchmark/io/http/http_ring.cpp
r3b402339 r144fa5c 9 9 #include <liburing.h> 10 10 11 // #define NOBATCHING 12 // #define USE_ASYNC 13 14 // Options passed to each threads 11 typedef enum { 12 EVENT_END, 13 EVENT_ACCEPT, 14 EVENT_REQUEST, 15 EVENT_ANSWER 16 } event_t; 17 18 struct __attribute__((aligned(128))) request_t { 19 event_t type; 20 int fd; 21 size_t length; 22 char * buff; 23 char data[0]; 24 25 static struct request_t * create(event_t type, size_t extra) { 26 auto ret = (struct request_t *)malloc(sizeof(struct request_t) + extra); 27 ret->type = type; 28 ret->length = extra; 29 ret->buff = ret->data; 30 return ret; 31 } 32 33 static struct request_t * create(event_t type) { 34 return create(type, 0); 35 } 36 }; 37 15 38 struct __attribute__((aligned(128))) options_t { 16 // Data passed to accept17 39 struct { 18 40 int sockfd; … … 22 44 } acpt; 23 45 24 // Termination notification25 46 int endfd; 26 27 // The ring to use for io28 47 struct io_uring * ring; 48 49 struct { 50 size_t subs = 0; 51 size_t cnts = 0; 52 } result; 29 53 }; 30 54 31 55 //========================================================= 32 // General statistics33 struct __attribute__((aligned(128))) stats_block_t {34 struct {35 volatile size_t conns = 0;36 volatile size_t reads = 0;37 volatile size_t writes = 0;38 volatile size_t full_writes = 0;39 } completions;40 41 struct {42 volatile size_t conns = 0;43 struct {44 volatile size_t pipes = 0;45 volatile size_t reset = 0;46 volatile size_t other = 0;47 } requests;48 49 struct {50 volatile size_t pipes = 0;51 volatile size_t reset = 0;52 volatile size_t other = 0;53 } answers;54 } errors;55 56 struct {57 volatile size_t current = 0;58 volatile size_t max = 0;59 volatile size_t used = 0;60 } conns;61 62 volatile size_t recycle_errors = 0;63 };64 65 // Each thread gets its own block of stats66 // and there is a global block for tallying at the end67 thread_local stats_block_t stats;68 stats_block_t global_stats;69 70 // Get an array of current connections71 // This is just for debugging, to make sure72 // no two state-machines get the same fd73 const size_t array_max = 25000;74 class connection * volatile conns[array_max] = { 0 };75 76 // Max fd we've seen, keep track so it's convenient to adjust the array size after77 volatile int max_fd = 0;78 79 //=========================================================80 // Some small wrappers for ring operations used outside the connection state machine81 // get sqe + error handling82 56 static struct io_uring_sqe * get_sqe(struct io_uring * ring) { 83 57 struct io_uring_sqe * sqe = io_uring_get_sqe(ring); … … 89 63 } 90 64 91 // read of the event fd is not done by a connection 92 // use nullptr as the user data 65 static void submit(struct io_uring * ) { 66 // io_uring_submit(ring); 67 } 68 69 //========================================================= 93 70 static void ring_end(struct io_uring * ring, int fd, char * buffer, size_t len) { 94 71 struct io_uring_sqe * sqe = get_sqe(ring); 95 72 io_uring_prep_read(sqe, fd, buffer, len, 0); 96 io_uring_sqe_set_data(sqe, nullptr); 97 io_uring_submit(ring); 73 io_uring_sqe_set_data(sqe, request_t::create(EVENT_END)); 74 submit(ring); 75 } 76 77 static void ring_accept(struct io_uring * ring, int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { 78 auto req = request_t::create(EVENT_ACCEPT); 79 struct io_uring_sqe * sqe = get_sqe(ring); 80 io_uring_prep_accept(sqe, sockfd, addr, addrlen, flags); 81 io_uring_sqe_set_data(sqe, req); 82 submit(ring); 83 // std::cout << "Submitted accept: " << req << std::endl; 84 } 85 86 static void ring_request(struct io_uring * ring, int fd) { 87 size_t size = 1024; 88 auto req = request_t::create(EVENT_REQUEST, size); 89 req->fd = fd; 90 91 struct io_uring_sqe * sqe = get_sqe(ring); 92 io_uring_prep_read(sqe, fd, req->buff, size, 0); 93 io_uring_sqe_set_data(sqe, req); 94 submit(ring); 95 // std::cout << "Submitted request: " << req << " (" << (void*)req->buffer << ")"<<std::endl; 98 96 } 99 97 100 98 //========================================================= 101 // All answers are fixed and determined by the return code102 99 enum HttpCode { 103 100 OK200 = 0, … … 111 108 }; 112 109 113 // Get a fix reply based on the return code114 110 const char * http_msgs[] = { 115 "HTTP/1.1 200 OK\ r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 15\r\nConnection: keep-alive\r\n\r\nHello, World!\r\n",116 "HTTP/1.1 400 Bad Request\ r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 0 \r\n\r\n",117 "HTTP/1.1 404 Not Found\ r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 0 \r\n\r\n",118 "HTTP/1.1 405 Method Not \r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 0 \r\n\r\n",119 "HTTP/1.1 408 Request Timeout\ r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 0 \r\n\r\n",120 "HTTP/1.1 413 Payload Too Large\ r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 0 \r\n\r\n",121 "HTTP/1.1 414 URI Too Long\ r\nServer: HttoForall\r\nContent-Type: text/plain\r\nContent-Length: 0 \r\n\r\n",111 "HTTP/1.1 200 OK\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: %zu \n\n%s", 112 "HTTP/1.1 400 Bad Request\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n", 113 "HTTP/1.1 404 Not Found\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n", 114 "HTTP/1.1 405 Method Not Allowed\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n", 115 "HTTP/1.1 408 Request Timeout\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n", 116 "HTTP/1.1 413 Payload Too Large\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n", 117 "HTTP/1.1 414 URI Too Long\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n", 122 118 }; 123 static_assert( KNOWN_CODES == (sizeof(http_msgs) / sizeof(http_msgs[0])) ); 124 125 // Pre-compute the length of these replys 126 const size_t http_lens[] = {127 strlen(http_msgs[0]),128 strlen(http_msgs[1]),129 strlen(http_msgs[2]),130 strlen(http_msgs[3]),131 strlen(http_msgs[4]),132 strlen(http_msgs[5]),133 strlen(http_msgs[6]),119 120 static_assert( KNOWN_CODES == (sizeof(http_msgs ) / sizeof(http_msgs [0]))); 121 122 const int http_codes[] = { 123 200, 124 400, 125 404, 126 405, 127 408, 128 413, 129 414, 134 130 }; 135 static_assert( KNOWN_CODES == (sizeof(http_lens) / sizeof(http_lens[0])) ); 131 132 static_assert( KNOWN_CODES == (sizeof(http_codes) / sizeof(http_codes[0]))); 133 134 int code_val(HttpCode code) { 135 return http_codes[code]; 136 } 137 138 static void ring_answer(struct io_uring * ring, int fd, HttpCode code) { 139 size_t size = 256; 140 auto req = request_t::create(EVENT_ANSWER, size); 141 req->fd = fd; 142 143 const char * fmt = http_msgs[code]; 144 const char * date = ""; 145 size = snprintf(req->buff, size, fmt, date, size); 146 147 struct io_uring_sqe * sqe = get_sqe(ring); 148 io_uring_prep_write(sqe, fd, req->buff, size, 0); 149 io_uring_sqe_set_data(sqe, req); 150 submit(ring); 151 // std::cout << "Submitted good answer: " << req << " (" << (void*)req->buffer << ")"<<std::endl; 152 } 153 154 static void ring_answer(struct io_uring * ring, int fd, const std::string &) { 155 // size_t size = 256; 156 // auto req = request_t::create(EVENT_ANSWER, size); 157 // req->fd = fd; 158 159 // const char * fmt = http_msgs[OK200]; 160 // const char * date = ""; 161 // size_t len = snprintf(req->buffer, size, fmt, date, ans.size(), ans.c_str()); 162 // req->length = len; 163 164 // struct io_uring_sqe * sqe = get_sqe(ring); 165 // io_uring_prep_write(sqe, fd, req->buffer, len, 0); 166 // io_uring_sqe_set_data(sqe, req); 167 // submit(ring); 168 // std::cout << "Submitted good answer: " << req << " (" << (void*)req->buffer << ")"<<std::endl; 169 170 171 static const char* RESPONSE = "HTTP/1.1 200 OK\r\n" \ 172 "Content-Length: 15\r\n" \ 173 "Content-Type: text/html\r\n" \ 174 "Connection: keep-alive\r\n" \ 175 "Server: testserver\r\n" \ 176 "\r\n" \ 177 "Hello, World!\r\n"; 178 179 static const size_t RLEN = strlen(RESPONSE); 180 181 size_t size = 256; 182 auto req = request_t::create(EVENT_ANSWER, size); 183 req->fd = fd; 184 req->buff = (char*)RESPONSE; 185 req->length = RLEN; 186 187 // const char * fmt = http_msgs[OK200]; 188 // const char * date = ""; 189 // size_t len = snprintf(req->buffer, size, fmt, date, ans.size(), ans.c_str()); 190 // req->length = len; 191 192 struct io_uring_sqe * sqe = get_sqe(ring); 193 io_uring_prep_write(sqe, fd, RESPONSE, RLEN, 0); 194 io_uring_sqe_set_data(sqe, req); 195 submit(ring); 196 } 136 197 137 198 //========================================================= 138 // Finate state machine responsible for handling each connection 139 class __attribute__((aligned(128))) connection { 140 private: 141 // The state of the machine 142 enum { 143 ACCEPTING, // Accept sent waiting for connection 144 REQUESTING, // Waiting for new request 145 ANSWERING, // Either request received submitting answer or short answer sent, need to submit rest 146 } state; 147 148 // The file descriptor of the connection 149 int fd; 150 151 // request data 152 static const size_t buffer_size = 1024; // Size of the read buffer 153 const char * buffer; // Buffer into which requests are read 154 155 // send data 156 size_t to_send; // Data left to send 157 const char * iterator; // Pointer to rest of the message to send 158 159 // stats 160 // how many requests/answers were complete, that is, a valid cqe was obtained 161 struct { 162 size_t requests = 0; 163 size_t answers = 0; 164 } stats; 165 166 private: 167 connection() 168 : state(ACCEPTING) 169 , fd(0) 170 , buffer( new char[buffer_size]) 171 , iterator(nullptr) 172 {} 173 174 ~connection() { 175 delete [] buffer; 176 ::stats.conns.current--; 177 } 178 179 // Close the current connection 180 void close(int err) { 181 // std::cout << "(" << this->stats.requests << "," << this->stats.answers << ", e" << err << ") "; 182 conns[fd] = nullptr; 183 184 if(fd != 0) { 185 ::close(fd); 186 } 187 delete this; 188 } 189 190 //-------------------------------------------------- 191 // Wrappers for submit so we can tweak it more easily 192 static void submit(struct io_uring * ring, struct io_uring_sqe * sqe, connection * conn) { 193 (void)ring; 194 #ifdef USE_ASYNC 195 io_uring_sqe_set_flags(sqe, IOSQE_ASYNC); 196 #endif 197 io_uring_sqe_set_data(sqe, conn); 198 #ifdef NOBATCHING 199 io_uring_submit(ring); 200 #endif 201 } 202 203 void submit(struct io_uring * ring, struct io_uring_sqe * sqe) { 204 submit(ring, sqe, this); 205 } 206 207 //-------------------------------------------------- 208 // get a new request from the client 209 void request(struct io_uring * ring) { 210 state = REQUESTING; 211 struct io_uring_sqe * sqe = get_sqe(ring); 212 io_uring_prep_recv(sqe, fd, (void*)buffer, buffer_size, 0); 213 submit(ring, sqe); 214 } 215 216 //-------------------------------------------------- 217 // Send a new answer based on a return code 218 void answer(struct io_uring * ring, HttpCode code) { 219 iterator = http_msgs[code]; 220 to_send = http_lens[code]; 221 if(to_send != 124) { 222 std::cerr << "Answer has weird size: " << to_send << " (" << (int)code << ")" << std::endl; 223 } 224 answer(ring); 225 } 226 227 // send a new answer to the client 228 // Reused for incomplete writes 229 void answer(struct io_uring * ring) { 230 state = ANSWERING; 231 struct io_uring_sqe * sqe = get_sqe(ring); 232 io_uring_prep_send(sqe, fd, iterator, to_send, 0); 233 submit(ring, sqe); 234 } 235 236 //-------------------------------------------------- 237 // Handle a new connection, results for getting an cqe while in the ACCEPTING state 238 void newconn(struct io_uring * ring, int ret) { 239 // Check errors 240 if( ret < 0 ) { 241 int err = -ret; 242 if( err == ECONNABORTED ) { 243 ::stats.errors.conns++; 244 this->close(err); 199 static void handle_new_conn(struct io_uring * ring, int fd) { 200 if( fd < 0 ) { 201 int err = -fd; 202 if( err == ECONNABORTED ) return; 203 std::cerr << "accept error: (" << errno << ") " << strerror(errno) << std::endl; 204 exit(EXIT_FAILURE); 205 } 206 207 ring_request(ring, fd); 208 } 209 210 static void handle_request(struct io_uring * ring, struct request_t * in, int res) { 211 if( res < 0 ) { 212 int err = -res; 213 switch(err) { 214 case EPIPE: 215 case ECONNRESET: 216 close(in->fd); 217 free(in); 245 218 return; 246 } 247 std::cerr << "accept error: (" << errno << ") " << strerror(errno) << std::endl; 248 exit(EXIT_FAILURE); 249 } 250 251 // Count the connections 252 ::stats.completions.conns++; 253 ::stats.conns.current++; 254 if(::stats.conns.current > ::stats.conns.max) { 255 ::stats.conns.max = ::stats.conns.current; 256 } 257 258 // Read on the data 259 fd = ret; 260 request(ring); 261 262 // check the max fd so we know if we exceeded the array 263 for(;;) { 264 int expected = max_fd; 265 if(expected >= fd) return; 266 if( __atomic_compare_exchange_n(&max_fd, &expected, fd, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) return; 267 } 268 269 // check if we have enough space to fit inside the array 270 if(fd >= array_max) { 271 std::cerr << "accept error: fd " << fd << " is too high" << std::endl; 272 return; 273 } 274 275 // Put our connection into the global array 276 // No one else should be using it so if they are that's a bug 277 auto exist = __atomic_exchange_n( &conns[fd], this, __ATOMIC_SEQ_CST); 278 if( exist ) { 279 size_t first = __atomic_fetch_add(&global_stats.recycle_errors, 1, __ATOMIC_SEQ_CST); 280 if( first == 0 ) { 281 std::cerr << "First: accept has existing connection " << std::endl; 282 } 283 } 284 } 285 286 // Handle a new request, results for getting an cqe while in the REQUESTING state 287 void newrequest(struct io_uring * ring, int res) { 288 // Check errors 289 if( res < 0 ) { 290 int err = -res; 291 switch(err) { 292 case EPIPE: 293 ::stats.errors.requests.pipes++; 294 break; 295 // Don't fall through the get better stats 296 case ECONNRESET: 297 ::stats.errors.requests.reset++; 298 break; 299 default: 300 ::stats.errors.requests.other++; 301 std::cerr << "request error: (" << err << ") " << strerror(err) << std::endl; 302 exit(EXIT_FAILURE); 303 } 304 305 // Connection failed, close it 306 this->close(err); 307 return; 308 } 309 310 // Update stats 311 ::stats.completions.reads++; 312 313 // Is this an EOF 314 if(res == 0) { 315 // Yes, close the connection 316 this->close(0); 317 return; 318 } 319 320 // Find the end of the request header 321 const char * it = buffer; 322 if( !strstr( it, "\r\n\r\n" ) ) { 323 // This state machine doesn't support incomplete reads 324 // Print them to output so it's clear there is an issue 325 std::cout << "Incomplete request" << std::endl; 326 this->close(EBADR); 327 return; 328 } 329 330 // Find the method to use 331 it = buffer; 332 int ret = memcmp(it, "GET ", 4); 333 if( ret != 0 ) { 334 // We only support get, answer with an error 335 answer(ring, E400); 336 return; 337 } 338 339 // Find the target 340 it += 4; 341 ret = memcmp(it, "/plaintext", 10); 342 if( ret != 0 ) { 343 // We only support /plaintext, answer with an error 344 answer(ring, E404); 345 return; 346 } 347 348 // Correct request, answer with the payload 349 this->stats.requests++; 350 answer(ring, OK200); 351 } 352 353 // Handle a partial or full answer sent, results for getting an cqe while in the ANSWERING state 354 void writedone(struct io_uring * ring, int res) { 355 // Check errors 356 if( res < 0 ) { 357 int err = -res; 358 switch(err) { 359 case EPIPE: 360 ::stats.errors.answers.pipes++; 361 break; 362 // Don't fall through the get better stats 363 case ECONNRESET: 364 ::stats.errors.answers.reset++; 365 break; 366 default: 367 ::stats.errors.answers.other++; 368 std::cerr << "answer error: (" << err << ") " << strerror(err) << std::endl; 369 exit(EXIT_FAILURE); 370 } 371 372 this->close(err); 373 return; 374 } 375 376 // Update stats 377 ::stats.completions.writes++; 378 if(res == 124) ::stats.completions.full_writes++; 379 380 // Is this write completed 381 if( res == to_send ) { 382 // Yes, more stats 383 this->stats.answers++; 384 if(this->stats.answers == 1) ::stats.conns.used++; 385 // Then read a new request 386 request(ring); 387 return; 388 } 389 390 // Not a completed read, push the rest 391 to_send -= res; 392 iterator += res; 393 answer(ring); 394 } 395 public: 396 // Submit a call to accept and create a new connection object 397 static void accept(struct io_uring * ring, const struct options_t & opt) { 398 struct io_uring_sqe * sqe = get_sqe(ring); 399 io_uring_prep_accept(sqe, opt.acpt.sockfd, opt.acpt.addr, opt.acpt.addrlen, opt.acpt.flags); 400 submit(ring, sqe, new connection()); 401 // std::cout << "Submitted accept: " << req << std::endl; 402 } 403 404 // Handle a new cqe 405 void handle(struct io_uring * ring, int res, const struct options_t & opt) { 406 switch(state) { 407 case ACCEPTING: 408 connection::accept(ring, opt); 409 newconn(ring, res); 410 break; 411 case REQUESTING: 412 newrequest(ring, res); 413 break; 414 case ANSWERING: 415 writedone(ring, res); 416 break; 417 } 418 } 419 }; 219 default: 220 std::cerr << "request error: (" << err << ") " << strerror(err) << std::endl; 221 exit(EXIT_FAILURE); 222 } 223 } 224 225 if(res == 0) { 226 close(in->fd); 227 free(in); 228 return; 229 } 230 231 const char * it = in->buff; 232 if( !strstr( it, "\r\n\r\n" ) ) { 233 std::cout << "Incomplete request" << std::endl; 234 close(in->fd); 235 free(in); 236 return; 237 } 238 239 it = in->buff; 240 const std::string reply = "Hello, World!\n"; 241 int ret = memcmp(it, "GET ", 4); 242 if( ret != 0 ) { 243 ring_answer(ring, in->fd, E400); 244 goto NEXT; 245 } 246 247 it += 4; 248 ret = memcmp(it, "/plaintext", 10); 249 if( ret != 0 ) { 250 ring_answer(ring, in->fd, E404); 251 goto NEXT; 252 } 253 254 ring_answer(ring, in->fd, reply); 255 256 NEXT: 257 ring_request(ring, in->fd); 258 return; 259 } 260 261 static void handle_answer(struct io_uring * ring, struct request_t * in, int res) { 262 if( res < 0 ) { 263 int err = -res; 264 switch(err) { 265 case EPIPE: 266 case ECONNRESET: 267 close(in->fd); 268 free(in); 269 return; 270 default: 271 std::cerr << "answer error: (" << err << ") " << strerror(err) << std::endl; 272 exit(EXIT_FAILURE); 273 } 274 } 275 276 if( res >= in->length ) { 277 free(in); 278 return; 279 } 280 281 struct io_uring_sqe * sqe = get_sqe(ring); 282 io_uring_prep_write(sqe, in->fd, in->buff + res, in->length - res, 0); 283 io_uring_sqe_set_data(sqe, in); 284 submit(ring); 285 // std::cout << "Re-Submitted request: " << in << " (" << (void*)in->buffer << ")"<<std::endl; 286 287 ring_request(ring, in->fd); 288 } 420 289 421 290 //========================================================= 422 // Main loop of the WebServer 423 // Effectively uses one thread_local copy of everything per kernel thread 291 extern "C" { 292 extern int __io_uring_flush_sq(struct io_uring *ring); 293 } 294 424 295 void * proc_loop(void * arg) { 425 // Get the thread local argument296 size_t count = 0; 426 297 struct options_t & opt = *(struct options_t *)arg; 298 427 299 struct io_uring * ring = opt.ring; 428 300 429 // Track the shutdown using a event_fd430 301 char endfd_buf[8]; 431 302 ring_end(ring, opt.endfd, endfd_buf, 8); 432 303 433 // Accept our first connection 434 // May not take effect until io_uring_submit_and_wait 435 connection::accept(ring, opt); 436 437 int reset = 1; // Counter to print stats once in a while 438 bool done = false; // Are we done 439 size_t sqes = 0; // Number of sqes we submitted 440 size_t call = 0; // Number of submits we made 304 ring_accept(ring, opt.acpt.sockfd, opt.acpt.addr, opt.acpt.addrlen, opt.acpt.flags); 305 306 bool done = false; 441 307 while(!done) { 442 // Submit all the answers we have and wait for responses 443 int ret = io_uring_submit_and_wait(ring, 1); 444 445 // check errors 446 if (ret < 0) { 447 fprintf( stderr, "io_uring S&W error: (%d) %s\n", (int)-ret, strerror(-ret) ); 308 struct io_uring_cqe *cqe; 309 int ret; 310 while(-EAGAIN == (ret = io_uring_wait_cqe_nr(ring, &cqe, 0))) { 311 ret = io_uring_submit_and_wait(ring, 1); 312 if (ret < 0) { 313 fprintf( stderr, "io_uring get error: (%d) %s\n", (int)-ret, strerror(-ret) ); 314 exit(EXIT_FAILURE); 315 } 316 opt.result.subs += ret; 317 opt.result.cnts++; 318 } 319 320 if (ret < 0 && -EAGAIN != ret) { 321 fprintf( stderr, "io_uring peek error: (%d) %s\n", (int)-ret, strerror(-ret) ); 448 322 exit(EXIT_FAILURE); 449 323 } 450 324 451 // Check how good we are at batching sqes 452 sqes += ret; 453 call++; 454 455 struct io_uring_cqe *cqe; 456 unsigned head; 457 unsigned count = 0; 458 459 // go through all cqes 460 io_uring_for_each_cqe(ring, head, cqe) { 461 if (0 == cqe->user_data) { 325 auto req = (struct request_t *)cqe->user_data; 326 // std::cout << req << " completed with " << cqe->res << std::endl; 327 328 switch(req->type) { 329 case EVENT_END: 462 330 done = true; 463 331 break; 464 } 465 466 auto req = (class connection *)cqe->user_data; 467 req->handle( ring, cqe->res, opt ); 468 469 // Every now and then, print some stats 470 reset--; 471 if(reset == 0) { 472 std::cout << "Submit average: " << sqes << "/" << call << "(" << (((double)sqes) / call) << ")" << std::endl; 473 // Reset to some random number of completions 474 // use the ring_fd in the number of threads don't all print at once 475 reset = 100000 + (100000 * (ring->ring_fd % 5)); 476 } 477 478 // Keep track of how many cqes we have seen 479 count++; 480 } 481 482 // Mark the cqes as seen 483 io_uring_cq_advance(ring, count); 484 } 485 486 // Tally all the thread local statistics 487 __atomic_fetch_add( &global_stats.completions.conns, ::stats.completions.conns, __ATOMIC_SEQ_CST ); 488 __atomic_fetch_add( &global_stats.completions.reads, ::stats.completions.reads, __ATOMIC_SEQ_CST ); 489 __atomic_fetch_add( &global_stats.completions.writes, ::stats.completions.writes, __ATOMIC_SEQ_CST ); 490 __atomic_fetch_add( &global_stats.completions.full_writes, ::stats.completions.full_writes, __ATOMIC_SEQ_CST ); 491 __atomic_fetch_add( &global_stats.errors.conns, ::stats.errors.conns, __ATOMIC_SEQ_CST ); 492 __atomic_fetch_add( &global_stats.errors.requests.pipes, ::stats.errors.requests.pipes, __ATOMIC_SEQ_CST ); 493 __atomic_fetch_add( &global_stats.errors.requests.reset, ::stats.errors.requests.reset, __ATOMIC_SEQ_CST ); 494 __atomic_fetch_add( &global_stats.errors.requests.other, ::stats.errors.requests.other, __ATOMIC_SEQ_CST ); 495 __atomic_fetch_add( &global_stats.errors.answers.pipes, ::stats.errors.answers.pipes, __ATOMIC_SEQ_CST ); 496 __atomic_fetch_add( &global_stats.errors.answers.reset, ::stats.errors.answers.reset, __ATOMIC_SEQ_CST ); 497 __atomic_fetch_add( &global_stats.errors.answers.other, ::stats.errors.answers.other, __ATOMIC_SEQ_CST ); 498 __atomic_fetch_add( &global_stats.conns.current, ::stats.conns.current, __ATOMIC_SEQ_CST ); 499 __atomic_fetch_add( &global_stats.conns.max, ::stats.conns.max, __ATOMIC_SEQ_CST ); 500 __atomic_fetch_add( &global_stats.conns.used, ::stats.conns.used, __ATOMIC_SEQ_CST ); 501 502 return nullptr; 332 case EVENT_ACCEPT: 333 handle_new_conn(ring, cqe->res); 334 free(req); 335 ring_accept(ring, opt.acpt.sockfd, opt.acpt.addr, opt.acpt.addrlen, opt.acpt.flags); 336 break; 337 case EVENT_REQUEST: 338 handle_request(ring, req, cqe->res); 339 break; 340 case EVENT_ANSWER: 341 handle_answer(ring, req, cqe->res); 342 break; 343 } 344 345 io_uring_cqe_seen(ring, cqe); 346 } 347 348 return (void*)count; 503 349 } 504 350 505 351 //========================================================= 506 #include <bit> // for ispow2 507 352 struct __attribute__((aligned(128))) aligned_ring { 353 struct io_uring storage; 354 }; 355 356 #include <bit> 357 358 #include <pthread.h> 508 359 extern "C" { 509 #include <pthread.h> // for pthreads 510 #include <signal.h> // for signal(SIGPIPE, SIG_IGN); 511 #include <sys/eventfd.h> // use for termination 512 #include <sys/socket.h> // for sockets in general 513 #include <netinet/in.h> // for sockaddr_in, AF_INET 360 #include <signal.h> 361 #include <sys/eventfd.h> 362 #include <sys/socket.h> 363 #include <netinet/in.h> 514 364 } 515 365 516 366 int main(int argc, char * argv[]) { 517 // Initialize the array of connection-fd associations518 for(int i = 0; i < array_max; i++) {519 conns[i] = nullptr;520 }521 522 // Make sure we ignore all sigpipes523 367 signal(SIGPIPE, SIG_IGN); 524 368 525 // Default command line arguments 526 unsigned nthreads = 1; // number of kernel threads 527 unsigned port = 8800; // which port to listen on 528 unsigned entries = 256; // number of entries per ring/kernel thread 529 unsigned backlog = 262144; // backlog argument to listen 530 bool attach = false; // Whether or not to attach all the rings 531 bool sqpoll = false; // Whether or not to use SQ Polling 532 533 //=================== 534 // Arguments Parsing 369 unsigned nthreads = 1; 370 unsigned port = 8800; 371 unsigned entries = 256; 372 unsigned backlog = 10; 373 bool attach = false; 374 375 //=================== 376 // Arguments 535 377 int c; 536 while ((c = getopt (argc, argv, "t:p:e:b:a S")) != -1) {378 while ((c = getopt (argc, argv, "t:p:e:b:a")) != -1) { 537 379 switch (c) 538 380 { … … 552 394 attach = true; 553 395 break; 554 case 'S':555 sqpoll = true;556 break;557 396 case '?': 558 397 default: 559 std::cerr << "Usage: -t <threads> -p <port> -e <entries> -b <backlog> -a S" << std::endl;398 std::cerr << "Usage: -t <threads> -p <port> -e <entries> -b <backlog> -a" << std::endl; 560 399 return EXIT_FAILURE; 561 400 } … … 577 416 //=================== 578 417 // End FD 579 // Create a single event fd to notify the kernel threads when the server shutsdown580 418 int efd = eventfd(0, EFD_SEMAPHORE); 581 419 if (efd < 0) { … … 586 424 //=================== 587 425 // Open Socket 588 // Listen on specified port589 426 std::cout << getpid() << " : Listening on port " << port << std::endl; 590 427 int server_fd = socket(AF_INET, SOCK_STREAM, 0); … … 602 439 address.sin_port = htons( port ); 603 440 604 // In case the port is already in use, don't just return an error605 // Linux is very slow at reclaiming port so just retry regularly606 441 int waited = 0; 607 442 while(true) { … … 609 444 if(ret < 0) { 610 445 if(errno == EADDRINUSE) { 611 // Port is in used let's retry later612 446 if(waited == 0) { 613 447 std::cerr << "Waiting for port" << std::endl; 614 448 } else { 615 // To be cure, print how long we have been waiting616 449 std::cerr << "\r" << waited; 617 450 std::cerr.flush(); 618 451 } 619 452 waited ++; 620 usleep( 1000000 ); // Wait and retry453 usleep( 1000000 ); 621 454 continue; 622 455 } 623 // Some other error occured, this is a real error624 456 std::cerr << "bind error: (" << errno << ") " << strerror(errno) << std::endl; 625 457 exit(EXIT_FAILURE); … … 642 474 std::cout << std::endl; 643 475 644 // Create the desired number of kernel-threads and for each645 // create a ring. Create the rings in the main so we can attach them646 // Since the rings are all in a dense VLA, aligned them so we don't get false sharing647 // it's unlikely but better safe than sorry648 struct __attribute__((aligned(128))) aligned_ring {649 struct io_uring storage;650 };651 476 aligned_ring thrd_rings[nthreads]; 652 477 pthread_t thrd_hdls[nthreads]; 653 478 options_t thrd_opts[nthreads]; 654 bool no_drops = true;655 bool fast_poll = true;656 bool nfix_sqpl = true;657 479 for(unsigned i = 0; i < nthreads; i++) { 658 struct io_uring_params p = { }; 659 660 if(sqpoll) { // If sqpoll is on, add the flag 661 p.flags |= IORING_SETUP_SQPOLL; 662 p.sq_thread_idle = 100; 663 } 664 665 if (attach && i != 0) { // If attach is on, add the flag, except for the first ring 666 p.flags |= IORING_SETUP_ATTACH_WQ; 480 if(!attach || i == 0) { 481 io_uring_queue_init(entries, &thrd_rings[i].storage, 0); 482 } 483 else { 484 struct io_uring_params p; 485 memset(&p, 0, sizeof(p)); 486 p.flags = IORING_SETUP_ATTACH_WQ; 667 487 p.wq_fd = thrd_rings[0].storage.ring_fd; 668 } 669 670 // Create the ring 671 io_uring_queue_init_params(entries, &thrd_rings[i].storage, &p); 672 673 // Check if some of the note-worthy features are there 674 if(0 == (p.features & IORING_FEAT_NODROP )) { no_drops = false; } 675 if(0 == (p.features & IORING_FEAT_FAST_POLL )) { fast_poll = false; } 676 if(0 == (p.features & IORING_FEAT_SQPOLL_NONFIXED)) { nfix_sqpl = false; } 677 678 // Write the socket options we want to the options we pass to the threads 488 io_uring_queue_init_params(entries, &thrd_rings[i].storage, &p); 489 } 490 679 491 thrd_opts[i].acpt.sockfd = server_fd; 680 492 thrd_opts[i].acpt.addr = (struct sockaddr *)&address; … … 691 503 } 692 504 693 // Tell the user if the features are present694 if( no_drops ) std::cout << "No Drop Present" << std::endl;695 if( fast_poll) std::cout << "Fast Poll Present" << std::endl;696 if(!nfix_sqpl) std::cout << "Non-Fixed SQ Poll not Present" << std::endl;697 698 505 //=================== 699 506 // Server Started … … 703 510 int ret; 704 511 do { 705 // Wait for a Ctrl-D to close the server706 512 ret = read(STDIN_FILENO, buffer, 128); 707 513 if(ret < 0) { … … 720 526 721 527 //=================== 722 // Use eventfd_write to tell the threads we are closing723 528 (std::cout << "Sending Shutdown to Threads... ").flush(); 724 529 ret = eventfd_write(efd, nthreads); … … 730 535 731 536 //=================== 732 // Join all the threads and close the rings733 537 (std::cout << "Stopping Threads Done... ").flush(); 538 size_t total = 0; 539 size_t count = 0; 734 540 for(unsigned i = 0; i < nthreads; i++) { 735 541 void * retval; … … 739 545 exit(EXIT_FAILURE); 740 546 } 547 // total += (size_t)retval; 548 total += thrd_opts[i].result.subs; 549 count += thrd_opts[i].result.cnts; 741 550 742 551 io_uring_queue_exit(thrd_opts[i].ring); 743 552 } 744 553 std::cout << "done" << std::endl; 745 746 //=================== 747 // Close the sockets554 std::cout << "Submit average: " << total << "/" << count << "(" << (((double)total) / count) << ")" << std::endl; 555 556 //=================== 748 557 (std::cout << "Closing Socket... ").flush(); 749 558 ret = shutdown( server_fd, SHUT_RD ); … … 758 567 exit(EXIT_FAILURE); 759 568 } 760 std::cout << "done" << std::endl << std::endl; 761 762 // Print stats and exit 763 std::cout << "Errors: " << global_stats.errors.conns << "c, (" << global_stats.errors.requests.pipes << "p, " << global_stats.errors.requests.reset << "r, " << global_stats.errors.requests.other << "o" << ")r, (" << global_stats.errors.answers.pipes << "p, " << global_stats.errors.answers.reset << "r, " << global_stats.errors.answers.other << "o" << ")a" << std::endl; 764 std::cout << "Completions: " << global_stats.completions.conns << "c, " << global_stats.completions.reads << "r, " << global_stats.completions.writes << "w" << std::endl; 765 std::cout << "Full Writes: " << global_stats.completions.full_writes << std::endl; 766 std::cout << "Max FD: " << max_fd << std::endl; 767 std::cout << "Successful connections: " << global_stats.conns.used << std::endl; 768 std::cout << "Max concurrent connections: " << global_stats.conns.max << std::endl; 769 std::cout << "Accepts on non-zeros: " << global_stats.recycle_errors << std::endl; 770 std::cout << "Leaked conn objects: " << global_stats.conns.current << std::endl; 771 } 772 773 // compile-command: "g++ http_ring.cpp -std=c++2a -pthread -luring -O3" // 569 std::cout << "done" << std::endl; 570 } -
doc/theses/andrew_beach_MMath/existing.tex
r3b402339 r144fa5c 12 12 obvious to the reader. 13 13 14 \section{\texorpdfstring{Overloading and \lstinline|extern|} 15 {Overloading and extern}} 14 \section{\texorpdfstring{Overloading and \lstinline|extern|}{Overloading and extern}} 16 15 \CFA has extensive overloading, allowing multiple definitions of the same name 17 16 to be defined.~\cite{Moss18} -
doc/theses/andrew_beach_MMath/features.tex
r3b402339 r144fa5c 7 7 Virtual types and casts are not required for a basic exception-system but are 8 8 useful for advanced exception features. However, \CFA is not object-oriented so 9 there is no obvious concept of virtuals. Hence, to create advanced exception9 there is no obvious concept of virtuals. Hence, to create advanced exception 10 10 features for this work, I needed to designed and implemented a virtual-like 11 11 system for \CFA. … … 30 30 \end{center} 31 31 The hierarchy provides the ability to handle an exception at different degrees 32 of specificity (left to right). Hence, it is possible to catch a more general32 of specificity (left to right). Hence, it is possible to catch a more general 33 33 exception-type in higher-level code where the implementation details are 34 34 unknown, which reduces tight coupling to the lower-level implementation. … … 78 78 79 79 Exceptions are defined by the trait system; there are a series of traits, and 80 if a type satisfies them, then it can be used as an exception. The following80 if a type satisfies them, then it can be used as an exception. The following 81 81 is the base trait all exceptions need to match. 82 82 \begin{cfa} … … 92 92 \PAB{I do not understand this paragraph.} 93 93 One odd thing about @get_exception_vtable@ is that it should always be a 94 constant function, returning the same value regardless of its argument. A94 constant function, returning the same value regardless of its argument. A 95 95 pointer or reference to the virtual table instance could be used instead, 96 96 however using a function has some ease of implementation advantages and allows 97 97 for easier disambiguation because the virtual type name (or the address of an 98 98 instance that is in scope) can be used instead of the mangled virtual table 99 name. Also note the use of the word ``promise'' in the trait99 name. Also note the use of the word ``promise'' in the trait 100 100 description. Currently, \CFA cannot check to see if either @exceptT@ or 101 101 @virtualT@ match the layout requirements. This is considered part of … … 126 126 127 127 Finally there are three convenience macros for referring to the these traits: 128 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@. Each128 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@. Each 129 129 takes the virtual type's name, and for polymorphic types only, the 130 130 parenthesized list of polymorphic arguments. These macros do the name mangling … … 212 212 expression has a type with a @void defaultResumptionHandler(T &)@ (default 213 213 handler) defined, where the handler is found at the call site by the type 214 system. At runtime, a representation of the exception type and an instance of214 system. At runtime, a representation of the exception type and an instance of 215 215 the exception type is \emph{not} copied because the stack is maintained during 216 216 the handler search. … … 306 306 exception matches, @CONDITION@ is executed. The condition expression may 307 307 reference all names in scope at the beginning of the try block and @NAME@ 308 introduced in the handler clause. If the condition is true, then the handler308 introduced in the handler clause. If the condition is true, then the handler 309 309 matches. Otherwise, the exception search continues at the next appropriate kind 310 310 of handler clause in the try block. … … 359 359 the end of the block. This requirement ensures always continues as if the 360 360 finally clause is not present, \ie finally is for cleanup not changing control 361 flow. Because of this requirement, local control flow out of the finally block362 is forbidden. The compiler precludes any @break@, @continue@, @fallthru@ or361 flow. Because of this requirement, local control flow out of the finally block 362 is forbidden. The compiler precludes any @break@, @continue@, @fallthru@ or 363 363 @return@ that causes control to leave the finally block. Other ways to leave 364 364 the finally block, such as a long jump or termination are much harder to check, … … 371 371 372 372 There is no special statement for starting a cancellation; instead the standard 373 library function @cancel_stack@ is called passing an exception. Unlike a373 library function @cancel_stack@ is called passing an exception. Unlike a 374 374 raise, this exception is not used in matching only to pass information about 375 375 the cause of the cancellation. … … 379 379 \item[Main Stack:] 380 380 The main stack is the one used by the program main at the start of execution, 381 and is the only stack in a sequential program. Hence, when cancellation is381 and is the only stack in a sequential program. Hence, when cancellation is 382 382 forwarded to the main stack, there is no other forwarding stack, so after the 383 383 stack is unwound, there is a program-level abort. … … 385 385 \item[Thread Stack:] 386 386 A thread stack is created for a @thread@ object or object that satisfies the 387 @is_thread@ trait. A thread only has two points of communication that must387 @is_thread@ trait. A thread only has two points of communication that must 388 388 happen: start and join. As the thread must be running to perform a 389 389 cancellation, it must occur after start and before join, so join is a 390 cancellation point. After the stack is unwound, the thread halts and waits for390 cancellation point. After the stack is unwound, the thread halts and waits for 391 391 another thread to join with it. The joining thread, checks for a cancellation, 392 392 and if present, resumes exception @ThreadCancelled@. … … 408 408 409 409 \item[Coroutine Stack:] A coroutine stack is created for a @coroutine@ object 410 or object that satisfies the @is_coroutine@ trait. A coroutine only knows of411 two other coroutines, its starter and its last resumer. The last resumer has412 the tightest coupling to the coroutine it activated. Hence, cancellation of410 or object that satisfies the @is_coroutine@ trait. A coroutine only knows of 411 two other coroutines, its starter and its last resumer. The last resumer has 412 the tightest coupling to the coroutine it activated. Hence, cancellation of 413 413 the active coroutine is forwarded to the last resumer after the stack is 414 414 unwound, as the last resumer has the most precise knowledge about the current -
doc/theses/andrew_beach_MMath/implement.tex
r3b402339 r144fa5c 278 278 @_URC_END_OF_STACK@. 279 279 280 Second, when a handler is matched, raise exception continues onto the cleanup 281 phase. 280 Second, when a handler is matched, raise exception continues onto the cleanup phase. 282 281 Once again, it calls the personality functions of each stack frame from newest 283 282 to oldest. This pass stops at the stack frame containing the matching handler. -
doc/theses/andrew_beach_MMath/thesis-frontpgs.tex
r3b402339 r144fa5c 36 36 37 37 A thesis \\ 38 presented to the University of Waterloo \\ 38 presented to the University of Waterloo \\ 39 39 in fulfillment of the \\ 40 40 thesis requirement for the degree of \\ … … 64 64 \cleardoublepage 65 65 66 66 67 67 %---------------------------------------------------------------------- 68 68 % EXAMINING COMMITTEE (Required for Ph.D. theses only) … … 71 71 \begin{center}\textbf{Examining Committee Membership}\end{center} 72 72 \noindent 73 The following served on the Examining Committee for this thesis. The decision 74 of the Examining Committee is by majority vote. 75 \bigskip 76 77 \noindent 78 \begin{tabbing} 79 Internal-External Member: \= \kill % using longest text to define tab length 80 External Examiner: \> Bruce Bruce \\ 73 The following served on the Examining Committee for this thesis. The decision of the Examining Committee is by majority vote. 74 \bigskip 75 76 \noindent 77 \begin{tabbing} 78 Internal-External Member: \= \kill % using longest text to define tab length 79 External Examiner: \> Bruce Bruce \\ 81 80 \> Professor, Dept. of Philosophy of Zoology, University of Wallamaloo \\ 82 \end{tabbing} 83 \bigskip 84 81 \end{tabbing} 82 \bigskip 83 85 84 \noindent 86 85 \begin{tabbing} … … 92 91 \end{tabbing} 93 92 \bigskip 94 93 95 94 \noindent 96 95 \begin{tabbing} … … 100 99 \end{tabbing} 101 100 \bigskip 102 101 103 102 \noindent 104 103 \begin{tabbing} … … 108 107 \end{tabbing} 109 108 \bigskip 110 109 111 110 \noindent 112 111 \begin{tabbing} … … 124 123 % December 13th, 2006. It is designed for an electronic thesis. 125 124 \noindent 126 I hereby declare that I am the sole author of this thesis. This is a true copy 127 of the thesis, including any required final revisions, as accepted by my 128 examiners. 129 130 \bigskip 131 125 I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. 126 127 \bigskip 128 132 129 \noindent 133 130 I understand that my thesis may be made electronically available to the public. -
doc/theses/andrew_beach_MMath/thesis.tex
r3b402339 r144fa5c 45 45 % FRONT MATERIAL 46 46 %---------------------------------------------------------------------- 47 \input{thesis-frontpgs} 47 \input{thesis-frontpgs} 48 48 49 49 %---------------------------------------------------------------------- … … 65 65 A \gls{computer} could compute $\pi$ all day long. In fact, subsets of digits 66 66 of $\pi$'s decimal approximation would make a good source for psuedo-random 67 vectors, \gls{rvec} . 67 vectors, \gls{rvec} . 68 68 69 69 %---------------------------------------------------------------------- … … 96 96 97 97 \begin{itemize} 98 \item A well-prepared PDF should be 98 \item A well-prepared PDF should be 99 99 \begin{enumerate} 100 100 \item Of reasonable size, {\it i.e.} photos cropped and compressed. 101 \item Scalable, to allow enlargment of text and drawings. 102 \end{enumerate} 101 \item Scalable, to allow enlargment of text and drawings. 102 \end{enumerate} 103 103 \item Photos must be bit maps, and so are not scaleable by definition. TIFF and 104 104 BMP are uncompressed formats, while JPEG is compressed. Most photos can be 105 105 compressed without losing their illustrative value. 106 \item Drawings that you make should be scalable vector graphics, \emph{not} 106 \item Drawings that you make should be scalable vector graphics, \emph{not} 107 107 bit maps. Some scalable vector file formats are: EPS, SVG, PNG, WMF. These can 108 all be converted into PNG or PDF, that pdflatex recognizes. Your drawing 109 package probably can export to one of these formats directly. Otherwise, a 110 common procedure is to print-to-file through a Postscript printer driver to 111 create a PS file, then convert that to EPS (encapsulated PS, which has a 112 bounding box to describe its exact size rather than a whole page). 108 all be converted into PNG or PDF, that pdflatex recognizes. Your drawing 109 package probably can export to one of these formats directly. Otherwise, a 110 common procedure is to print-to-file through a Postscript printer driver to 111 create a PS file, then convert that to EPS (encapsulated PS, which has a 112 bounding box to describe its exact size rather than a whole page). 113 113 Programs such as GSView (a Ghostscript GUI) can create both EPS and PDF from 114 114 PS files. Appendix~\ref{AppendixA} shows how to generate properly sized Matlab 115 115 plots and save them as PDF. 116 116 \item It's important to crop your photos and draw your figures to the size that 117 you want to appear in your thesis. Scaling photos with the 118 includegraphics command will cause loss of resolution. And scaling down 117 you want to appear in your thesis. Scaling photos with the 118 includegraphics command will cause loss of resolution. And scaling down 119 119 drawings may cause any text annotations to become too small. 120 120 \end{itemize} 121 121 122 122 For more information on \LaTeX\, see the uWaterloo Skills for the 123 Academic Workplace \href{https://uwaterloo.ca/information-systems-technology/services/electronic-thesis-preparation-and-submission-support/ethesis-guide/creating-pdf-version-your-thesis/creating-pdf-files-using-latex/latex-ethesis-and-large-documents}{course notes}. 123 Academic Workplace \href{https://uwaterloo.ca/information-systems-technology/services/electronic-thesis-preparation-and-submission-support/ethesis-guide/creating-pdf-version-your-thesis/creating-pdf-files-using-latex/latex-ethesis-and-large-documents}{course notes}. 124 124 \footnote{ 125 125 Note that while it is possible to include hyperlinks to external documents, 126 it is not wise to do so, since anything you can't control may change over time. 127 It \emph{would} be appropriate and necessary to provide external links to 128 additional resources for a multimedia ``enhanced'' thesis. 129 But also note that if the \package{hyperref} package is not included, 130 as for the print-optimized option in this thesis template, any \cmmd{href} 126 it is not wise to do so, since anything you can't control may change over time. 127 It \emph{would} be appropriate and necessary to provide external links to 128 additional resources for a multimedia ``enhanced'' thesis. 129 But also note that if the \package{hyperref} package is not included, 130 as for the print-optimized option in this thesis template, any \cmmd{href} 131 131 commands in your logical document are no longer defined. 132 132 A work-around employed by this thesis template is to define a dummy 133 \cmmd{href} command (which does nothing) in the preamble of the document, 134 before the \package{hyperref} package is included. 133 \cmmd{href} command (which does nothing) in the preamble of the document, 134 before the \package{hyperref} package is included. 135 135 The dummy definition is then redifined by the 136 136 \package{hyperref} package when it is included. … … 138 138 139 139 The classic book by Leslie Lamport \cite{lamport.book}, author of \LaTeX , is 140 worth a look too, and the many available add-on packages are described by 140 worth a look too, and the many available add-on packages are described by 141 141 Goossens \textit{et al} \cite{goossens.book}. 142 142 … … 180 180 Export Setup button in the figure Property Editor. 181 181 182 \section{From the Command Line} 182 \section{From the Command Line} 183 183 All figure properties can also be manipulated from the command line. Here's an 184 example: 184 example: 185 185 \begin{verbatim} 186 186 x=[0:0.1:pi]; -
doc/theses/andrew_beach_MMath/uw-ethesis-frontpgs.tex
r3b402339 r144fa5c 30 30 \normalsize 31 31 A thesis \\ 32 presented to the University of Waterloo \\ 32 presented to the University of Waterloo \\ 33 33 in fulfillment of the \\ 34 34 thesis requirement for the degree of \\ … … 47 47 \end{titlepage} 48 48 49 % The rest of the front pages should contain no headers and be numbered using 50 % Roman numerals starting with `ii'. 49 % The rest of the front pages should contain no headers and be numbered using Roman numerals starting with `ii' 51 50 \pagestyle{plain} 52 51 \setcounter{page}{2} 53 52 54 \cleardoublepage % Ends the current page and causes all figures and tables 55 % that have so far appeared in the input to be printed. In a two-sided 56 % printing style, it also makes the next page a right-hand (odd-numbered) 57 % page, producing a blank page if necessary. 53 \cleardoublepage % Ends the current page and causes all figures and tables that have so far appeared in the input to be printed. 54 % In a two-sided printing style, it also makes the next page a right-hand (odd-numbered) page, producing a blank page if necessary. 58 55 59 \begin{comment} 56 \begin{comment} 60 57 % E X A M I N I N G C O M M I T T E E (Required for Ph.D. theses only) 61 58 % Remove or comment out the lines below to remove this page 62 59 \begin{center}\textbf{Examining Committee Membership}\end{center} 63 60 \noindent 64 The following served on the Examining Committee for this thesis. 65 The decision of the Examining Committee is by majority vote. 61 The following served on the Examining Committee for this thesis. The decision of the Examining Committee is by majority vote. 66 62 \bigskip 67 63 68 64 \noindent 69 65 \begin{tabbing} 70 66 Internal-External Member: \= \kill % using longest text to define tab length 71 External Examiner: \> Bruce Bruce \\ 67 External Examiner: \> Bruce Bruce \\ 72 68 \> Professor, Dept. of Philosophy of Zoology, University of Wallamaloo \\ 73 \end{tabbing} 69 \end{tabbing} 74 70 \bigskip 75 71 76 72 \noindent 77 73 \begin{tabbing} … … 83 79 \end{tabbing} 84 80 \bigskip 85 81 86 82 \noindent 87 83 \begin{tabbing} … … 91 87 \end{tabbing} 92 88 \bigskip 93 89 94 90 \noindent 95 91 \begin{tabbing} … … 99 95 \end{tabbing} 100 96 \bigskip 101 97 102 98 \noindent 103 99 \begin{tabbing} … … 115 111 % December 13th, 2006. It is designed for an electronic thesis. 116 112 \begin{center}\textbf{Author's Declaration}\end{center} 117 113 118 114 \noindent 119 I hereby declare that I am the sole author of this thesis. This is a true copy 120 of the thesis, including any required final revisions, as accepted by my 121 examiners. 115 I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. 122 116 123 117 \bigskip 124 118 125 119 \noindent 126 120 I understand that my thesis may be made electronically available to the public. -
doc/theses/andrew_beach_MMath/uw-ethesis.tex
r3b402339 r144fa5c 1 1 %====================================================================== 2 % University of Waterloo Thesis Template for LaTeX 3 % Last Updated November, 2020 4 % by Stephen Carr, IST Client Services, 2 % University of Waterloo Thesis Template for LaTeX 3 % Last Updated November, 2020 4 % by Stephen Carr, IST Client Services, 5 5 % University of Waterloo, 200 University Ave. W., Waterloo, Ontario, Canada 6 6 % FOR ASSISTANCE, please send mail to request@uwaterloo.ca 7 7 8 8 % DISCLAIMER 9 % To the best of our knowledge, this template satisfies the current uWaterloo 10 % thesis requirements. However, it is your responsibility to assure that you 11 % have met all requirements of the University and your particular department. 12 13 % Many thanks for the feedback from many graduates who assisted the 14 % development of this template. Also note that there are explanatory comments 15 % and tips throughout this template. 9 % To the best of our knowledge, this template satisfies the current uWaterloo thesis requirements. 10 % However, it is your responsibility to assure that you have met all requirements of the University and your particular department. 11 12 % Many thanks for the feedback from many graduates who assisted the development of this template. 13 % Also note that there are explanatory comments and tips throughout this template. 16 14 %====================================================================== 17 15 % Some important notes on using this template and making it your own... 18 16 19 % The University of Waterloo has required electronic thesis submission since 20 % October 2006. See the uWaterloo thesis regulations at: 21 % https://uwaterloo.ca/graduate-studies/thesis. 22 % This thesis template is geared towards generating a PDF version optimized 23 % for viewing on an electronic display, including hyperlinks within the PDF. 24 25 % DON'T FORGET TO ADD YOUR OWN NAME AND TITLE in the "hyperref" package 26 % configuration below. THIS INFORMATION GETS EMBEDDED IN THE FINAL PDF 27 % DOCUMENT. You can view the information if you view properties of the PDF. 28 29 % Many faculties/departments also require one or more printed copies. 30 % This template attempts to satisfy both types of output. 17 % The University of Waterloo has required electronic thesis submission since October 2006. 18 % See the uWaterloo thesis regulations at 19 % https://uwaterloo.ca/graduate-studies/thesis. 20 % This thesis template is geared towards generating a PDF version optimized for viewing on an electronic display, including hyperlinks within the PDF. 21 22 % DON'T FORGET TO ADD YOUR OWN NAME AND TITLE in the "hyperref" package configuration below. 23 % THIS INFORMATION GETS EMBEDDED IN THE PDF FINAL PDF DOCUMENT. 24 % You can view the information if you view properties of the PDF document. 25 26 % Many faculties/departments also require one or more printed copies. 27 % This template attempts to satisfy both types of output. 31 28 % See additional notes below. 32 % It is based on the standard "book" document class which provides all 33 % necessary sectioning structures and allows multi-part theses. 34 35 % If you are using this template in Overleaf (cloud-based collaboration 36 % service), then it is automatically processed and previewed for you as you 37 % edit. 38 39 % For people who prefer to install their own LaTeX distributions on their own 40 % computers, and process the source files manually, the following notes 41 % provide the sequence of tasks: 42 29 % It is based on the standard "book" document class which provides all necessary sectioning structures and allows multi-part theses. 30 31 % If you are using this template in Overleaf (cloud-based collaboration service), then it is automatically processed and previewed for you as you edit. 32 33 % For people who prefer to install their own LaTeX distributions on their own computers, and process the source files manually, the following notes provide the sequence of tasks: 34 43 35 % E.g. to process a thesis called "mythesis.tex" based on this template, run: 44 36 45 37 % pdflatex mythesis -- first pass of the pdflatex processor 46 38 % bibtex mythesis -- generates bibliography from .bib data file(s) 47 % makeindex -- should be run only if an index is used 48 % pdflatex mythesis -- fixes numbering in cross-references, bibliographic 49 % references, glossaries, index, etc. 50 % pdflatex mythesis -- it takes a couple of passes to completely process all 51 % cross-references 52 53 % If you use the recommended LaTeX editor, Texmaker, you would open the 54 % mythesis.tex file, then click the PDFLaTeX button. Then run BibTeX (under 55 % the Tools menu). Then click the PDFLaTeX button two more times. 56 % If you have an index as well, you'll need to run MakeIndex from the Tools 57 % menu as well, before running pdflatex the last two times. 58 59 % N.B. The "pdftex" program allows graphics in the following formats to be 60 % included with the "\includegraphics" command: PNG, PDF, JPEG, TIFF 61 % Tip: Generate your figures and photos in the size you want them to appear 62 % in your thesis, rather than scaling them with \includegraphics options. 63 % Tip: Any drawings you do should be in scalable vector graphic formats: SVG, 64 % PNG, WMF, EPS and then converted to PNG or PDF, so they are scalable in the 65 % final PDF as well. 39 % makeindex -- should be run only if an index is used 40 % pdflatex mythesis -- fixes numbering in cross-references, bibliographic references, glossaries, index, etc. 41 % pdflatex mythesis -- it takes a couple of passes to completely process all cross-references 42 43 % If you use the recommended LaTeX editor, Texmaker, you would open the mythesis.tex file, then click the PDFLaTeX button. Then run BibTeX (under the Tools menu). 44 % Then click the PDFLaTeX button two more times. 45 % If you have an index as well,you'll need to run MakeIndex from the Tools menu as well, before running pdflatex 46 % the last two times. 47 48 % N.B. The "pdftex" program allows graphics in the following formats to be included with the "\includegraphics" command: PNG, PDF, JPEG, TIFF 49 % Tip: Generate your figures and photos in the size you want them to appear in your thesis, rather than scaling them with \includegraphics options. 50 % Tip: Any drawings you do should be in scalable vector graphic formats: SVG, PNG, WMF, EPS and then converted to PNG or PDF, so they are scalable in the final PDF as well. 66 51 % Tip: Photographs should be cropped and compressed so as not to be too large. 67 52 68 % To create a PDF output that is optimized for double-sided printing: 69 % 1) comment-out the \documentclass statement in the preamble below, and 70 % un-comment the second \documentclass line. 71 % 2) change the value assigned below to the boolean variable "PrintVersion" 72 % from " false" to "true". 73 74 % ====================================================================== 53 % To create a PDF output that is optimized for double-sided printing: 54 % 1) comment-out the \documentclass statement in the preamble below, and un-comment the second \documentclass line. 55 % 2) change the value assigned below to the boolean variable "PrintVersion" from " false" to "true". 56 57 %====================================================================== 75 58 % D O C U M E N T P R E A M B L E 76 % Specify the document class, default style attributes, page dimensions, etc.59 % Specify the document class, default style attributes, and page dimensions, etc. 77 60 % For hyperlinked PDF, suitable for viewing on a computer, use this: 78 61 \documentclass[letterpaper,12pt,titlepage,oneside,final]{book} 79 62 80 % For PDF, suitable for double-sided printing, change the PrintVersion 81 % variable below to "true" and use this \documentclass line instead of the 82 % one above: 63 % For PDF, suitable for double-sided printing, change the PrintVersion variable below to "true" and use this \documentclass line instead of the one above: 83 64 %\documentclass[letterpaper,12pt,titlepage,openright,twoside,final]{book} 84 65 85 66 % Some LaTeX commands I define for my own nomenclature. 86 % If you have to, it's easier to make changes to nomenclature once here than 87 % in a million places throughout your thesis! 67 % If you have to, it's easier to make changes to nomenclature once here than in a million places throughout your thesis! 88 68 \newcommand{\package}[1]{\textbf{#1}} % package names in bold text 89 \newcommand{\cmmd}[1]{\textbackslash\texttt{#1}} % command name in tt font 90 \newcommand{\href}[1]{#1} % does nothing, but defines the command so the 91 % print-optimized version will ignore \href tags (redefined by hyperref pkg). 69 \newcommand{\cmmd}[1]{\textbackslash\texttt{#1}} % command name in tt font 70 \newcommand{\href}[1]{#1} % does nothing, but defines the command so the print-optimized version will ignore \href tags (redefined by hyperref pkg). 92 71 %\newcommand{\texorpdfstring}[2]{#1} % does nothing, but defines the command 93 72 % Anything defined here may be redefined by packages added below... … … 97 76 \newboolean{PrintVersion} 98 77 \setboolean{PrintVersion}{false} 99 % CHANGE THIS VALUE TO "true" as necessary, to improve printed results for 100 % hard copies by overriding some options of the hyperref package, called below. 78 % CHANGE THIS VALUE TO "true" as necessary, to improve printed results for hard copies by overriding some options of the hyperref package, called below. 101 79 102 80 %\usepackage{nomencl} % For a nomenclature (optional; available from ctan.org) 103 % Lots of math symbols and environments 104 \usepackage{amsmath,amssymb,amstext} 105 % For including graphics N.B. pdftex graphics driver 106 \usepackage[pdftex]{graphicx} 81 \usepackage{amsmath,amssymb,amstext} % Lots of math symbols and environments 82 \usepackage[pdftex]{graphicx} % For including graphics N.B. pdftex graphics driver 107 83 108 84 % Hyperlinks make it very easy to navigate an electronic document. 109 % In addition, this is where you should specify the thesis title and author as 110 % they appear in the properties of the PDF document. 85 % In addition, this is where you should specify the thesis title and author as they appear in the properties of the PDF document. 111 86 % Use the "hyperref" package 112 87 % N.B. HYPERREF MUST BE THE LAST PACKAGE LOADED; ADD ADDITIONAL PKGS ABOVE 113 88 \usepackage[pdftex,pagebackref=true]{hyperref} % with basic options 114 89 %\usepackage[pdftex,pagebackref=true]{hyperref} 115 % N.B. pagebackref=true provides links back from the References to the body 116 % text. This can cause trouble for printing. 90 % N.B. pagebackref=true provides links back from the References to the body text. This can cause trouble for printing. 117 91 \hypersetup{ 118 92 plainpages=false, % needed if Roman numbers in frontpages … … 122 96 pdffitwindow=false, % window fit to page when opened 123 97 pdfstartview={FitH}, % fits the width of the page to the window 124 % pdftitle={uWaterloo\ LaTeX\ Thesis\ Template}, % title: CHANGE THIS TEXT!98 % pdftitle={uWaterloo\ LaTeX\ Thesis\ Template}, % title: CHANGE THIS TEXT! 125 99 % pdfauthor={Author}, % author: CHANGE THIS TEXT! and uncomment this line 126 100 % pdfsubject={Subject}, % subject: CHANGE THIS TEXT! and uncomment this line 127 % pdfkeywords={keyword1} {key2} {key3}, % optional list of keywords101 % pdfkeywords={keyword1} {key2} {key3}, % list of keywords, and uncomment this line if desired 128 102 pdfnewwindow=true, % links in new window 129 103 colorlinks=true, % false: boxed links; true: colored links … … 133 107 urlcolor=cyan % color of external links 134 108 } 135 % for improved print quality, change some hyperref options 136 \ifthenelse{\boolean{PrintVersion}}{ 109 \ifthenelse{\boolean{PrintVersion}}{ % for improved print quality, change some hyperref options 137 110 \hypersetup{ % override some previously defined hyperref options 138 111 % colorlinks,% … … 143 116 }{} % end of ifthenelse (no else) 144 117 145 % Exception to the rule of hyperref being the last add-on package 146 \usepackage[automake,toc,abbreviations]{glossaries-extra} 147 % If glossaries-extra is not in your LaTeX distribution, get it from CTAN 148 % (http://ctan.org/pkg/glossaries-extra), although it's supposed to be in 149 % both the TeX Live and MikTeX distributions. There are also documentation 150 % and installation instructions there. 118 \usepackage[automake,toc,abbreviations]{glossaries-extra} % Exception to the rule of hyperref being the last add-on package 119 % If glossaries-extra is not in your LaTeX distribution, get it from CTAN (http://ctan.org/pkg/glossaries-extra), 120 % although it's supposed to be in both the TeX Live and MikTeX distributions. There are also documentation and 121 % installation instructions there. 151 122 152 123 % Setting up the page margins... 153 \setlength{\textheight}{9in} 154 \setlength{\topmargin}{-0.45in} 155 \setlength{\headsep}{0.25in} 156 % uWaterloo thesis requirements specify a minimum of 1 inch (72pt) margin at 157 % the top, bottom, and outside page edges and a 1.125 in. (81pt) gutter margin 158 % (on binding side). While this is not an issue for electronic viewing, a PDF 159 % may be printed, and so we have the same page layout for both printed and 160 % electronic versions, we leave the gutter margin in. Set margins to minimum 161 % permitted by uWaterloo thesis regulations: 124 \setlength{\textheight}{9in}\setlength{\topmargin}{-0.45in}\setlength{\headsep}{0.25in} 125 % uWaterloo thesis requirements specify a minimum of 1 inch (72pt) margin at the 126 % top, bottom, and outside page edges and a 1.125 in. (81pt) gutter margin (on binding side). 127 % While this is not an issue for electronic viewing, a PDF may be printed, and so we have the same page layout for both printed and electronic versions, we leave the gutter margin in. 128 % Set margins to minimum permitted by uWaterloo thesis regulations: 162 129 \setlength{\marginparwidth}{0pt} % width of margin notes 163 130 % N.B. If margin notes are used, you must adjust \textwidth, \marginparwidth 164 131 % and \marginparsep so that the space left between the margin notes and page 165 132 % edge is less than 15 mm (0.6 in.) 166 % width of space between body text and margin notes 167 \setlength{\marginparsep}{0pt} 168 % Adds 1/8 in. to binding side of all 133 \setlength{\marginparsep}{0pt} % width of space between body text and margin notes 134 \setlength{\evensidemargin}{0.125in} % Adds 1/8 in. to binding side of all 169 135 % even-numbered pages when the "twoside" printing option is selected 170 \setlength{\evensidemargin}{0.125in} 171 % Adds 1/8 in. to the left of all pages when "oneside" printing is selected, 172 % and to the left of all odd-numbered pages when "twoside" printing is selected 173 \setlength{\oddsidemargin}{0.125in} 174 % assuming US letter paper (8.5 in. x 11 in.) and side margins as above 175 \setlength{\textwidth}{6.375in} 136 \setlength{\oddsidemargin}{0.125in} % Adds 1/8 in. to the left of all pages when "oneside" printing is selected, and to the left of all odd-numbered pages when "twoside" printing is selected 137 \setlength{\textwidth}{6.375in} % assuming US letter paper (8.5 in. x 11 in.) and side margins as above 176 138 \raggedbottom 177 139 178 % The following statement specifies the amount of space between paragraphs. 179 % Other reasonable specifications are \bigskipamount and \smallskipamount. 140 % The following statement specifies the amount of space between paragraphs. Other reasonable specifications are \bigskipamount and \smallskipamount. 180 141 \setlength{\parskip}{\medskipamount} 181 142 182 % The following statement controls the line spacing. 183 % The default spacing corresponds to good typographic conventions and only 184 % slight changes (e.g., perhaps "1.2"), if any, should be made. 143 % The following statement controls the line spacing. 144 % The default spacing corresponds to good typographic conventions and only slight changes (e.g., perhaps "1.2"), if any, should be made. 185 145 \renewcommand{\baselinestretch}{1} % this is the default line space setting 186 146 187 147 % By default, each chapter will start on a recto (right-hand side) page. 188 % We also force each section of the front pages to start on a recto page by 189 % inserting \cleardoublepage commands. In many cases, this will require that 190 % the verso (left-hand) page be blank, and while it should be counted, a page 191 % number should not be printed. The following statements ensure a page number 192 % is not printed on an otherwise blank verso page. 148 % We also force each section of the front pages to start on a recto page by inserting \cleardoublepage commands. 149 % In many cases, this will require that the verso (left-hand) page be blank, and while it should be counted, a page number should not be printed. 150 % The following statements ensure a page number is not printed on an otherwise blank verso page. 193 151 \let\origdoublepage\cleardoublepage 194 152 \newcommand{\clearemptydoublepage}{% … … 196 154 \let\cleardoublepage\clearemptydoublepage 197 155 198 % Define Glossary terms (This is properly done here, in the preamble and 199 % could also be \input{} from a separate file...) 156 % Define Glossary terms (This is properly done here, in the preamble and could also be \input{} from a separate file...) 200 157 \input{glossaries} 201 158 \makeglossaries … … 212 169 % L O G I C A L D O C U M E N T 213 170 % The logical document contains the main content of your thesis. 214 % Being a large document, it is a good idea to divide your thesis into several 215 % files, each one containing one chapter or other significant chunk of content, 216 % so you can easily shuffle things around later if desired. 171 % Being a large document, it is a good idea to divide your thesis into several files, each one containing one chapter or other significant chunk of content, so you can easily shuffle things around later if desired. 217 172 %====================================================================== 218 173 \begin{document} … … 221 176 % FRONT MATERIAL 222 177 % title page,declaration, borrowers' page, abstract, acknowledgements, 223 % dedication, table of contents, list of tables, list of figures, 224 % nomenclature, etc. 225 %---------------------------------------------------------------------- 226 \input{uw-ethesis-frontpgs} 178 % dedication, table of contents, list of tables, list of figures, nomenclature, etc. 179 %---------------------------------------------------------------------- 180 \input{uw-ethesis-frontpgs} 227 181 228 182 %---------------------------------------------------------------------- 229 183 % MAIN BODY 230 184 % We suggest using a separate file for each chapter of your thesis. 231 % Start each chapter file with the \chapter command. Only use \documentclass,232 % \begin{document} and \end{document} commands in this master document.185 % Start each chapter file with the \chapter command. 186 % Only use \documentclass or \begin{document} and \end{document} commands in this master document. 233 187 % Tip: Putting each sentence on a new line is a way to simplify later editing. 234 188 %---------------------------------------------------------------------- … … 246 200 % Bibliography 247 201 248 % The following statement selects the style to use for references. 249 % It controls the sort order of the entries in the bibliography and also the 250 % formatting for the in-text labels. 202 % The following statement selects the style to use for references. 203 % It controls the sort order of the entries in the bibliography and also the formatting for the in-text labels. 251 204 \bibliographystyle{plain} 252 % This specifies the location of the file containing the bibliographic 253 % information. It assumes you're using BibTeX to manage your references (if 254 % not, why not?). 255 \cleardoublepage % This is needed if the "book" document class is used, to 256 % place the anchor in the correct page, because the bibliography will start 257 % on its own page. 258 % Use \clearpage instead if the document class uses the "oneside" argument. 259 \phantomsection % With hyperref package, enables hyperlinking from the table 260 % of contents to bibliography. 261 % The following statement causes the title "References" to be used for the 262 % bibliography section: 205 % This specifies the location of the file containing the bibliographic information. 206 % It assumes you're using BibTeX to manage your references (if not, why not?). 207 \cleardoublepage % This is needed if the "book" document class is used, to place the anchor in the correct page, because the bibliography will start on its own page. 208 % Use \clearpage instead if the document class uses the "oneside" argument 209 \phantomsection % With hyperref package, enables hyperlinking from the table of contents to bibliography 210 % The following statement causes the title "References" to be used for the bibliography section: 263 211 \renewcommand*{\bibname}{References} 264 212 … … 267 215 268 216 \bibliography{uw-ethesis,pl} 269 % Tip: You can create multiple .bib files to organize your references. Just 270 % list them all in the \bibliogaphy command, separated by commas (no spaces). 271 272 % The following statement causes the specified references to be added to the 273 % bibliography even if they were not cited in the text. The asterisk is a 274 % wildcard that causes all entries in the bibliographic database to be 275 % included (optional). 217 % Tip: You can create multiple .bib files to organize your references. 218 % Just list them all in the \bibliogaphy command, separated by commas (no spaces). 219 220 % The following statement causes the specified references to be added to the bibliography even if they were not cited in the text. 221 % The asterisk is a wildcard that causes all entries in the bibliographic database to be included (optional). 276 222 % \nocite{*} 277 223 %---------------------------------------------------------------------- … … 281 227 % The \appendix statement indicates the beginning of the appendices. 282 228 \appendix 283 % Add an un-numbered title page before the appendices and a line in the Table 284 % of Contents 229 % Add an un-numbered title page before the appendices and a line in the Table of Contents 285 230 % \chapter*{APPENDICES} 286 231 % \addcontentsline{toc}{chapter}{APPENDICES} 287 % Appendices are just more chapters, with different labeling (letters instead 288 % of numbers). 232 % Appendices are just more chapters, with different labeling (letters instead of numbers). 289 233 % \input{appendix-matlab_plots.tex} 290 234 291 % GLOSSARIES (Lists of definitions, abbreviations, symbols, etc. 292 % provided by the glossaries-extra package) 235 % GLOSSARIES (Lists of definitions, abbreviations, symbols, etc. provided by the glossaries-extra package) 293 236 % ----------------------------- 294 237 \printglossaries -
libcfa/src/memory.cfa
r3b402339 r144fa5c 10 10 // Created On : Tue Jun 2 16:48:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Feb 1 16:10:00 202113 // Update Count : 112 // Last Modified On : Tue Jun 3 12:30:00 2020 13 // Update Count : 0 14 14 // 15 15 … … 56 56 } 57 57 58 forall(T & | sized(T) )58 forall(T & | sized(T) | { void ^?{}(T &); }) 59 59 void ?{}(counter_ptr(T) & this, counter_ptr(T) that) { 60 60 // `that` is a copy but it should have neither a constructor 61 61 // nor destructor run on it so it shouldn't need adjustment. 62 internal_decrement(this); 62 63 internal_copy(this, that); 63 64 } … … 65 66 forall(T & | sized(T), Args... | { void ?{}(T&, Args); }) 66 67 void ?{}(counter_ptr(T) & this, Args args) { 67 this.data = malloc(); 68 this.data->counter = 1; 69 (this.data->object){args}; 68 this.data = (counter_data(T)*)new(args); 70 69 } 71 70 … … 127 126 forall(T & | sized(T), Args... | { void ?{}(T &, Args); }) 128 127 void ?{}(unique_ptr(T) & this, Args args) { 129 this.data = malloc(); 130 (*this.data){args}; 128 this.data = (T *)new(args); 131 129 } 132 130 -
libcfa/src/memory.hfa
r3b402339 r144fa5c 10 10 // Created On : Tue Jun 2 16:48:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jan 29 15:52:00 202113 // Update Count : 112 // Last Modified On : Tue Jun 3 12:29:00 2020 13 // Update Count : 0 14 14 // 15 15 … … 17 17 18 18 // Internal data object. 19 forall(T & | sized(T)) 20 struct counter_data {21 unsigned int counter;22 T object;23 };19 forall(T & | sized(T)) { 20 struct counter_data { 21 unsigned int counter; 22 T object; 23 }; 24 24 25 forall(T & | sized(T),Args... | { void ?{}(T &, Args); })26 void ?{}(counter_data(T) & this, Args args);25 forall(Args... | { void ?{}(T &, Args); }) 26 void ?{}(counter_data(T) & this, Args args); 27 27 28 forall(T & | sized(T) | { void ^?{}(T &); }) 29 void ^?{}(counter_data(T) & this); 28 forall( | { void ^?{}(T &); }) 29 void ^?{}(counter_data(T) & this); 30 } 30 31 31 32 // This is one of many pointers keeping this alive. 32 forall(T & | sized(T)) 33 struct counter_ptr {34 counter_data(T) * data;35 };33 forall(T & | sized(T)) { 34 struct counter_ptr { 35 counter_data(T) * data; 36 }; 36 37 37 forall(T & | sized(T)) 38 void ?{}(counter_ptr(T) & this); 39 forall(T & | sized(T)) 40 void ?{}(counter_ptr(T) & this, zero_t); 41 forall(T & | sized(T)) 42 void ?{}(counter_ptr(T) & this, counter_ptr(T) that); 43 forall(T & | sized(T), Args... | { void ?{}(T&, Args); }) 44 void ?{}(counter_ptr(T) & this, Args args); 38 void ?{}(counter_ptr(T) & this); 39 void ?{}(counter_ptr(T) & this, zero_t); 40 forall( | { void ^?{}(T &); }) 41 void ?{}(counter_ptr(T) & this, counter_ptr(T) that); 42 forall(Args... | { void ?{}(T&, Args); }) 43 void ?{}(counter_ptr(T) & this, Args args); 45 44 46 forall(T & | sized(T)| { void ^?{}(T &); })47 void ^?{}(counter_ptr(T) & this);45 forall( | { void ^?{}(T &); }) 46 void ^?{}(counter_ptr(T) & this); 48 47 49 forall(T & | sized(T)) 50 T & *?(counter_ptr(T) & this); 48 T & *?(counter_ptr(T) & this); 51 49 52 forall(T & | sized(T)| { void ^?{}(T &); })53 void ?=?(counter_ptr(T) & this, counter_ptr(T) that);54 forall(T & | sized(T)| { void ^?{}(T &); })55 void ?=?(counter_ptr(T) & this, zero_t);50 forall( | { void ^?{}(T &); }) 51 void ?=?(counter_ptr(T) & this, counter_ptr(T) that); 52 forall( | { void ^?{}(T &); }) 53 void ?=?(counter_ptr(T) & this, zero_t); 56 54 57 forall(T & | sized(T)) 58 int ?==?(counter_ptr(T) const & this, counter_ptr(T) const & that); 59 forall(T & | sized(T)) 60 int ?!=?(counter_ptr(T) const & this, counter_ptr(T) const & that); 61 forall(T & | sized(T)) 62 int ?==?(counter_ptr(T) const & this, zero_t); 63 forall(T & | sized(T)) 64 int ?!=?(counter_ptr(T) const & this, zero_t); 55 int ?==?(counter_ptr(T) const & this, counter_ptr(T) const & that); 56 int ?!=?(counter_ptr(T) const & this, counter_ptr(T) const & that); 57 int ?==?(counter_ptr(T) const & this, zero_t); 58 int ?!=?(counter_ptr(T) const & this, zero_t); 59 } 65 60 66 61 // This is the only pointer that keeps this alive. 67 forall(T &) 68 struct unique_ptr {69 T * data;70 };62 forall(T &) { 63 struct unique_ptr { 64 T * data; 65 }; 71 66 72 forall(T &) 73 void ?{}(unique_ptr(T) & this); 74 forall(T &) 75 void ?{}(unique_ptr(T) & this, zero_t); 76 forall(T &) 77 void ?{}(unique_ptr(T) & this, unique_ptr(T) that) = void; 78 forall(T & | sized(T), Args... | { void ?{}(T &, Args); }) 79 void ?{}(unique_ptr(T) & this, Args args); 67 void ?{}(unique_ptr(T) & this); 68 void ?{}(unique_ptr(T) & this, zero_t); 69 void ?{}(unique_ptr(T) & this, unique_ptr(T) that) = void; 70 forall( | sized(T), Args... | { void ?{}(T &, Args); }) 71 void ?{}(unique_ptr(T) & this, Args args); 80 72 81 forall(T &| { void ^?{}(T &); })82 void ^?{}(unique_ptr(T) & this);73 forall( | { void ^?{}(T &); }) 74 void ^?{}(unique_ptr(T) & this); 83 75 84 forall(T & ) 85 T & *?(unique_ptr(T) & this); 76 T & *?(unique_ptr(T) & this); 86 77 87 forall(T &) 88 void ?=?(unique_ptr(T) & this, unique_ptr(T) that) = void; 89 forall(T & | { void ^?{}(T &); }) 90 void ?=?(unique_ptr(T) & this, zero_t); 78 void ?=?(unique_ptr(T) & this, unique_ptr(T) that) = void; 79 forall( | { void ^?{}(T &); }) 80 void ?=?(unique_ptr(T) & this, zero_t); 91 81 92 forall(T &| { void ^?{}(T &); })93 void move(unique_ptr(T) & this, unique_ptr(T) & that);82 forall( | { void ^?{}(T &); }) 83 void move(unique_ptr(T) & this, unique_ptr(T) & that); 94 84 95 forall(T &) 96 int ?==?(unique_ptr(T) const & this, unique_ptr(T) const & that); 97 forall(T &) 98 int ?!=?(unique_ptr(T) const & this, unique_ptr(T) const & that); 99 forall(T &) 100 int ?==?(unique_ptr(T) const & this, zero_t); 101 forall(T &) 102 int ?!=?(unique_ptr(T) const & this, zero_t); 85 int ?==?(unique_ptr(T) const & this, unique_ptr(T) const & that); 86 int ?!=?(unique_ptr(T) const & this, unique_ptr(T) const & that); 87 int ?==?(unique_ptr(T) const & this, zero_t); 88 int ?!=?(unique_ptr(T) const & this, zero_t); 89 } -
tests/smart-pointers.cfa
r3b402339 r144fa5c 2 2 3 3 #include <memory.hfa> 4 #include < assert.h>4 #include <stdlib.hfa> 5 5 6 6 void counter_test(void) { … … 53 53 } 54 54 55 void declare_test(void) {56 counter_ptr(int) ptr_i0 = 3;57 counter_ptr(char) ptr_c0 = 'a';58 counter_ptr(float) ptr_f0 = 3.5f;59 counter_ptr(double) ptr_d0 = 3.5;60 61 unique_ptr(int) ptr_i1 = 3;62 unique_ptr(char) ptr_c1 = 'a';63 unique_ptr(float) ptr_f1 = 3.5f;64 unique_ptr(double) ptr_d1 = 3.5;65 }66 67 55 int main(int argc, char * argv[]) { 68 56 counter_test(); 69 57 unique_test(); 70 58 pointer_equality(); 71 72 printf("done\n");73 59 }
Note:
See TracChangeset
for help on using the changeset viewer.