… | |
… | |
53 | REQ_STAT, REQ_LSTAT, REQ_FSTAT, |
53 | REQ_STAT, REQ_LSTAT, REQ_FSTAT, |
54 | REQ_FSYNC, REQ_FDATASYNC, |
54 | REQ_FSYNC, REQ_FDATASYNC, |
55 | REQ_UNLINK, REQ_RMDIR, REQ_RENAME, |
55 | REQ_UNLINK, REQ_RMDIR, REQ_RENAME, |
56 | REQ_READDIR, |
56 | REQ_READDIR, |
57 | REQ_LINK, REQ_SYMLINK, |
57 | REQ_LINK, REQ_SYMLINK, |
|
|
58 | REQ_GROUP, |
58 | }; |
59 | }; |
59 | |
60 | |
60 | #define AIO_CB_KLASS "IO::AIO::CB" |
61 | #define AIO_REQ_KLASS "IO::AIO::REQ" |
|
|
62 | #define AIO_GRP_KLASS "IO::AIO::GRP" |
61 | |
63 | |
62 | typedef struct aio_cb |
64 | typedef struct aio_cb |
63 | { |
65 | { |
64 | struct aio_cb *grp_prev, *grp_next; |
66 | struct aio_cb *grp, *grp_prev, *grp_next; |
65 | struct aio_grp *grp; |
|
|
66 | |
67 | |
67 | struct aio_cb *volatile next; |
68 | struct aio_cb *volatile next; |
68 | |
69 | |
69 | SV *self; /* the perl counterpart of this request, if any */ |
70 | SV *self; /* the perl counterpart of this request, if any */ |
70 | |
71 | |
… | |
… | |
84 | unsigned char cancelled; |
85 | unsigned char cancelled; |
85 | } aio_cb; |
86 | } aio_cb; |
86 | |
87 | |
87 | typedef aio_cb *aio_req; |
88 | typedef aio_cb *aio_req; |
88 | typedef aio_cb *aio_req_ornot; |
89 | typedef aio_cb *aio_req_ornot; |
|
|
90 | typedef aio_cb *aio_group; |
89 | |
91 | |
90 | static int started, wanted; |
92 | static int started, wanted; |
91 | static volatile int nreqs; |
93 | static volatile int nreqs; |
92 | static int max_outstanding = 1<<30; |
94 | static int max_outstanding = 1<<30; |
93 | static int respipe [2]; |
95 | static int respipe [2]; |
… | |
… | |
97 | static pthread_cond_t reqwait = PTHREAD_COND_INITIALIZER; |
99 | static pthread_cond_t reqwait = PTHREAD_COND_INITIALIZER; |
98 | |
100 | |
99 | static volatile aio_req reqs, reqe; /* queue start, queue end */ |
101 | static volatile aio_req reqs, reqe; /* queue start, queue end */ |
100 | static volatile aio_req ress, rese; /* queue start, queue end */ |
102 | static volatile aio_req ress, rese; /* queue start, queue end */ |
101 | |
103 | |
102 | typedef struct aio_grp |
|
|
103 | { |
|
|
104 | struct aio_cb *first, *last; |
|
|
105 | SV *callback; |
|
|
106 | int busycount; |
|
|
107 | } aio_grp; |
|
|
108 | |
|
|
109 | static void aio_grp_begin (aio_grp *grp) |
|
|
110 | { |
|
|
111 | ++grp->busycount; |
|
|
112 | } |
|
|
113 | |
|
|
114 | static void aio_grp_end (aio_grp *grp) |
|
|
115 | { |
|
|
116 | --grp->busycount; |
|
|
117 | |
|
|
118 | if (grp->busycount) |
|
|
119 | return; |
|
|
120 | |
|
|
121 | SvREFCNT_dec (grp->callback); |
|
|
122 | grp->callback = 0; |
|
|
123 | } |
|
|
124 | |
|
|
125 | static aio_grp *aio_grp_new () |
|
|
126 | { |
|
|
127 | aio_grp *grp; |
|
|
128 | |
|
|
129 | Newz (0, grp, 1, aio_grp); |
|
|
130 | aio_grp_begin (grp); |
|
|
131 | |
|
|
132 | return grp; |
|
|
133 | } |
|
|
134 | |
|
|
135 | /* must be called at most once */ |
104 | /* must be called at most once */ |
136 | static SV *req_sv (aio_req req) |
105 | static SV *req_sv (aio_req req, const char *klass) |
137 | { |
106 | { |
138 | req->self = (SV *)newHV (); |
107 | req->self = (SV *)newHV (); |
139 | sv_magic (req->self, 0, PERL_MAGIC_ext, (char *)req, 0); |
108 | sv_magic (req->self, 0, PERL_MAGIC_ext, (char *)req, 0); |
140 | |
109 | |
141 | return sv_bless (newRV_noinc (req->self), gv_stashpv (AIO_CB_KLASS, 1)); |
110 | return sv_2mortal (sv_bless (newRV_noinc (req->self), gv_stashpv (klass, 1))); |
142 | } |
111 | } |
143 | |
112 | |
144 | static aio_req SvAIO_REQ (SV *sv) |
113 | static aio_req SvAIO_REQ (SV *sv, const char *klass) |
145 | { |
114 | { |
146 | if (!sv_derived_from (sv, AIO_CB_KLASS) || !SvROK (sv)) |
115 | if (!sv_derived_from (sv, klass) || !SvROK (sv)) |
147 | croak ("object of class " AIO_CB_KLASS " expected"); |
116 | croak ("object of class %s expected", klass); |
148 | |
117 | |
149 | MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext); |
118 | MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext); |
150 | |
119 | |
151 | return mg ? (aio_req)mg->mg_ptr : 0; |
120 | return mg ? (aio_req)mg->mg_ptr : 0; |
152 | } |
121 | } |
… | |
… | |
846 | |
815 | |
847 | #define REQ_SEND \ |
816 | #define REQ_SEND \ |
848 | req_send (req); \ |
817 | req_send (req); \ |
849 | \ |
818 | \ |
850 | if (GIMME_V != G_VOID) \ |
819 | if (GIMME_V != G_VOID) \ |
851 | XPUSHs (req_sv (req)); |
820 | XPUSHs (req_sv (req, AIO_REQ_KLASS)); |
852 | |
821 | |
853 | MODULE = IO::AIO PACKAGE = IO::AIO |
822 | MODULE = IO::AIO PACKAGE = IO::AIO |
854 | |
823 | |
855 | PROTOTYPES: ENABLE |
824 | PROTOTYPES: ENABLE |
856 | |
825 | |
… | |
… | |
1103 | req->dataptr = SvPVbyte_nolen (req->data); |
1072 | req->dataptr = SvPVbyte_nolen (req->data); |
1104 | |
1073 | |
1105 | REQ_SEND; |
1074 | REQ_SEND; |
1106 | } |
1075 | } |
1107 | |
1076 | |
1108 | #if 0 |
|
|
1109 | |
|
|
1110 | # undocumented, because it does not cancel active requests |
|
|
1111 | void |
1077 | void |
1112 | cancel_most_requests () |
1078 | aio_group (callback=&PL_sv_undef) |
|
|
1079 | SV * callback |
1113 | PROTOTYPE: |
1080 | PROTOTYPE: ;& |
1114 | CODE: |
1081 | PPCODE: |
1115 | { |
1082 | { |
1116 | aio_req *req; |
1083 | dREQ; |
1117 | |
1084 | req->type = REQ_GROUP; |
1118 | pthread_mutex_lock (&reqlock); |
1085 | XPUSHs (req_sv (req, AIO_GRP_KLASS)); |
1119 | for (req = reqs; req; req = req->next) |
|
|
1120 | req->flags |= 1; |
|
|
1121 | pthread_mutex_unlock (&reqlock); |
|
|
1122 | |
|
|
1123 | pthread_mutex_lock (&reslock); |
|
|
1124 | for (req = ress; req; req = req->next) |
|
|
1125 | req->flags |= 1; |
|
|
1126 | pthread_mutex_unlock (&reslock); |
|
|
1127 | } |
1086 | } |
1128 | |
|
|
1129 | #endif |
|
|
1130 | |
1087 | |
1131 | void |
1088 | void |
1132 | flush () |
1089 | flush () |
1133 | PROTOTYPE: |
1090 | PROTOTYPE: |
1134 | CODE: |
1091 | CODE: |
… | |
… | |
1177 | CODE: |
1134 | CODE: |
1178 | RETVAL = nreqs; |
1135 | RETVAL = nreqs; |
1179 | OUTPUT: |
1136 | OUTPUT: |
1180 | RETVAL |
1137 | RETVAL |
1181 | |
1138 | |
1182 | MODULE = IO::AIO PACKAGE = IO::AIO::CB |
1139 | MODULE = IO::AIO PACKAGE = IO::AIO::REQ |
1183 | |
1140 | |
1184 | void |
1141 | void |
1185 | cancel (aio_req_ornot req) |
1142 | cancel (aio_req_ornot req) |
1186 | PROTOTYPE: |
1143 | PROTOTYPE: |
1187 | CODE: |
1144 | CODE: |