1 /* 2 * Copyright (C) 2000-2018 the xine project 3 * 4 * This file is part of xine, a free video player. 5 * 6 * xine is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * xine is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 19 */ 20 21 #ifndef HAVE_XINE_TICKETS_H 22 #define HAVE_XINE_TICKETS_H 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 /* 29 * xine thread tickets. 30 * This is similar to a rw lock in "prefer writers" mode. 31 * - Shared recursive read lock: acquire () / release () 32 * - Recursive write lock: revoke () / issue () 33 * plus there are a few special hacks. 34 * - Low overhead temporary read unlock: renew () 35 * (better than release () + acquire ()). 36 * Mutex less check ticket_revoked whether it is time to do so. 37 * Yes this may delay writers a bit due to multicore data cache 38 * sync issues (and your check interval, of course) but since 39 * writing is rare we accept that. 40 * Alternatively, register a revoke notify callback that stops 41 * waiting for something else. 42 * - Read lock with priority over writers: "irrevocable" 43 * (use for known quick actions only). 44 * - Top level uninterruptible write lock: "atomic". 45 * Note that the write side is for engine internal use. 46 * It now also supports turning an already held read into write 47 * temporarily. 48 */ 49 50 typedef void xine_ticket_revoke_cb_t (void *user_data, int flags); 51 typedef struct xine_ticket_s xine_ticket_t; 52 53 struct xine_ticket_s { 54 55 /* the ticket owner must assure to check for ticket revocation in 56 * intervals of finite length; this means that you must release 57 * the ticket before any operation that might block 58 * 59 * you must never write to this member directly 60 */ 61 int ticket_revoked; 62 63 /* apply for a ticket; between acquire and relese of an irrevocable 64 * ticket (be sure to pair them properly!), it is guaranteed that you 65 * will never be blocked by ticket revocation */ 66 void (*acquire)(xine_ticket_t *self, int irrevocable); 67 68 /* give a ticket back */ 69 void (*release)(xine_ticket_t *self, int irrevocable); 70 71 /* renew a ticket, when it has been revoked, see ticket_revoked above; 72 * irrevocable must be set to one, if your thread might have acquired 73 * irrevocable tickets you don't know of; set it to zero only when 74 * you know that this is impossible. */ 75 void (*renew)(xine_ticket_t *self, int irrevocable); 76 77 #ifdef XINE_ENGINE_INTERNAL 78 /* XXX: port rewiring in the middle of a decoder loop iteration is a bad idea. 79 * We could make that halfway safe by (un)referencing post ports consistently. 80 * Unfortunately, post plugins intercept our calls at will. 81 * Even worse, we ourselves told them to inline _x_post_rewire () then 82 * still use the previous port :-/ 83 * KLUDGE: 84 * - We now have 2 levels of revocation, plain and rewire. 85 * - If there is a pending rewire, ticket_revoked has the rewire flag set. 86 * - A pending or incoming rewire revoke repels plain renewers, so they 87 * can advance to a code location more suitable for a rewire, then 88 * renew again with rewire flag set. 89 * - Output layer get funcs return an emergency buffer/frame if engine is paused. 90 * Why the f**k didnt we allow NULL there?? 91 * - Decoder loops let the full thing go right before next iteration. */ 92 #define XINE_TICKET_FLAG_ATOMIC 1 93 #define XINE_TICKET_FLAG_REWIRE 2 94 95 /* allow handing out new tickets. atomic needs to be same as below. */ 96 void (*issue)(xine_ticket_t *self, int flags); 97 98 /* revoke all tickets and deny new ones; 99 * a pair of atomic revoke and issue cannot be interrupted by another 100 * revocation or by other threads acquiring tickets. 101 * set rewire flag to also do that lock. */ 102 void (*revoke)(xine_ticket_t *self, int flags); 103 104 /* behaves like acquire() but doesn't block the calling thread; when 105 * the thread would have been blocked, 0 is returned otherwise 1 106 * this function acquires a ticket even if ticket revocation is active */ 107 int (*acquire_nonblocking)(xine_ticket_t *self, int irrevocable); 108 109 /* behaves like release() but doesn't block the calling thread; should 110 * be used in combination with acquire_nonblocking() */ 111 void (*release_nonblocking)(xine_ticket_t *self, int irrevocable); 112 113 /* forbid port rewiring for critical code sections. */ 114 int (*lock_port_rewiring)(xine_ticket_t *self, int ms_timeout); 115 void (*unlock_port_rewiring)(xine_ticket_t *self); 116 117 void (*dispose)(xine_ticket_t *self); 118 119 /* (un)register a revoke notify callback, telling the current revoke flags. 120 * Return from it does not * imply anything about the ticket itself, 121 * it just shall shorten wait. 122 * Note that unregister needs the same data pointer as well to 123 * handle multiple instances of the same object. */ 124 void (*revoke_cb_register) (xine_ticket_t *self, xine_ticket_revoke_cb_t *cb, void *user_data); 125 void (*revoke_cb_unregister)(xine_ticket_t *self, xine_ticket_revoke_cb_t *cb, void *user_data); 126 #endif 127 }; 128 129 #ifdef __cplusplus 130 } 131 #endif 132 133 #endif 134