fastqueue-lib 0.0.16__tar.gz → 0.0.18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastqueue-lib-0.0.16/fastqueue_lib.egg-info → fastqueue_lib-0.0.18}/PKG-INFO +10 -8
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/README.md +2 -5
- fastqueue_lib-0.0.18/fastqueue/__init__.py +3 -0
- fastqueue_lib-0.0.18/fastqueue/__init__.pyi +39 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/fastqueue/prototypes.py +21 -28
- fastqueue_lib-0.0.18/fastqueue/py.typed +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18/fastqueue_lib.egg-info}/PKG-INFO +10 -8
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/fastqueue_lib.egg-info/SOURCES.txt +3 -1
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/pyproject.toml +1 -1
- fastqueue_lib-0.0.18/src/ccqueue.cpp +131 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/src/cllqueue.cpp +28 -12
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/src/fastqueue.c +324 -383
- fastqueue_lib-0.0.18/tests/test_memory.py +1030 -0
- fastqueue_lib-0.0.18/tests/test_queue.py +673 -0
- fastqueue-lib-0.0.16/fastqueue/__init__.py +0 -3
- fastqueue-lib-0.0.16/fastqueue.py +0 -144
- fastqueue-lib-0.0.16/src/ccqueue.cpp +0 -89
- fastqueue-lib-0.0.16/tests/test_queue.py +0 -248
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/LICENSE +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/MANIFEST.in +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/fastqueue_lib.egg-info/dependency_links.txt +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/fastqueue_lib.egg-info/requires.txt +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/fastqueue_lib.egg-info/top_level.txt +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/setup.cfg +0 -0
- {fastqueue-lib-0.0.16 → fastqueue_lib-0.0.18}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fastqueue-lib
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.18
|
|
4
4
|
Summary: Fast single ended queue library for python
|
|
5
5
|
Author-email: Matthew Taylor <matthew.taylor.andre@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/MatthewAndreTaylor/fastqueue
|
|
@@ -19,9 +19,14 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
20
|
Requires-Python: >=3.7
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
22
23
|
Provides-Extra: examples
|
|
24
|
+
Requires-Dist: matplotlib; extra == "examples"
|
|
25
|
+
Requires-Dist: numpy; extra == "examples"
|
|
26
|
+
Requires-Dist: pandas; extra == "examples"
|
|
23
27
|
Provides-Extra: tests
|
|
24
|
-
|
|
28
|
+
Requires-Dist: pytest; extra == "tests"
|
|
29
|
+
Dynamic: license-file
|
|
25
30
|
|
|
26
31
|
# fastqueue
|
|
27
32
|
|
|
@@ -31,7 +36,7 @@ License-File: LICENSE
|
|
|
31
36
|
[](https://pypi.org/project/fastqueue-lib/)
|
|
32
37
|
|
|
33
38
|
|
|
34
|
-
Single
|
|
39
|
+
Single-ended fast queues built in C tuned for Python.
|
|
35
40
|
|
|
36
41
|
## Requirements
|
|
37
42
|
|
|
@@ -39,7 +44,7 @@ Single ended fast queue's built in C tuned for python.
|
|
|
39
44
|
|
|
40
45
|
## Installation
|
|
41
46
|
|
|
42
|
-
To install fastqueue, using pip:
|
|
47
|
+
To install fastqueue, using [pip](https://pypi.org/project/fastqueue-lib):
|
|
43
48
|
|
|
44
49
|
```bash
|
|
45
50
|
pip install fastqueue-lib
|
|
@@ -93,9 +98,6 @@ True
|
|
|
93
98
|
['🚒', '🛴', '🚅', '🚗']
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
Another alternative is `fastqueue.LockQueue()` which supports all queue operations.
|
|
97
|
-
`fastqueue.LockQueue()` is built as a thread-safe alternative to the other queue types.
|
|
98
|
-
|
|
99
101
|
## Example Benchmarks
|
|
100
102
|
|
|
101
103
|
### Queue operations
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://pypi.org/project/fastqueue-lib/)
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
Single
|
|
9
|
+
Single-ended fast queues built in C tuned for Python.
|
|
10
10
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ Single ended fast queue's built in C tuned for python.
|
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
17
|
-
To install fastqueue, using pip:
|
|
17
|
+
To install fastqueue, using [pip](https://pypi.org/project/fastqueue-lib):
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
pip install fastqueue-lib
|
|
@@ -68,9 +68,6 @@ True
|
|
|
68
68
|
['🚒', '🛴', '🚅', '🚗']
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
Another alternative is `fastqueue.LockQueue()` which supports all queue operations.
|
|
72
|
-
`fastqueue.LockQueue()` is built as a thread-safe alternative to the other queue types.
|
|
73
|
-
|
|
74
71
|
## Example Benchmarks
|
|
75
72
|
|
|
76
73
|
### Queue operations
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
fastqueue
|
|
3
|
+
=====
|
|
4
|
+
|
|
5
|
+
* Queue
|
|
6
|
+
* QueueC
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
from typing import Any, Optional
|
|
10
|
+
from collections.abc import Iterable
|
|
11
|
+
from typing_extensions import Self
|
|
12
|
+
|
|
13
|
+
__all__ = "Queue", "QueueC"
|
|
14
|
+
|
|
15
|
+
class Queue:
|
|
16
|
+
def __init__(self, iterable: Optional[Iterable] = None) -> None: ...
|
|
17
|
+
def enqueue(self, item: Any) -> None: ...
|
|
18
|
+
def dequeue(self) -> Any: ...
|
|
19
|
+
def extend(self, items: Iterable[Any]) -> None: ...
|
|
20
|
+
def clear(self) -> None: ...
|
|
21
|
+
def __len__(self) -> int: ...
|
|
22
|
+
def __getitem__(self, index: int) -> Any: ...
|
|
23
|
+
def __setitem__(self, index: int, item: Any) -> None: ...
|
|
24
|
+
def __contains__(self, item: Any) -> bool: ...
|
|
25
|
+
def copy(self) -> Self: ...
|
|
26
|
+
def __copy__(self) -> Self: ...
|
|
27
|
+
|
|
28
|
+
class QueueC:
|
|
29
|
+
def __init__(self, iterable: Optional[Iterable] = None) -> None: ...
|
|
30
|
+
def enqueue(self, item: Any) -> None: ...
|
|
31
|
+
def dequeue(self) -> Any: ...
|
|
32
|
+
def extend(self, items: Iterable[Any]) -> None: ...
|
|
33
|
+
def clear(self) -> None: ...
|
|
34
|
+
def __len__(self) -> int: ...
|
|
35
|
+
def __getitem__(self, index: int) -> Any: ...
|
|
36
|
+
def __setitem__(self, index: int, item: Any) -> None: ...
|
|
37
|
+
def __contains__(self, item: Any) -> bool: ...
|
|
38
|
+
def copy(self) -> Self: ...
|
|
39
|
+
def __copy__(self) -> Self: ...
|
|
@@ -27,20 +27,21 @@ class LLNodeQueue(Structure):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
__libfile = Path(__file__).parent / "cllqueue.so"
|
|
30
|
-
|
|
30
|
+
# Native calls own Python references and must keep the GIL.
|
|
31
|
+
llqueue_lib = PyDLL(str(__libfile))
|
|
31
32
|
|
|
32
33
|
llqueue_lib.new_node_queue.argtypes = []
|
|
33
34
|
llqueue_lib.new_node_queue.restype = POINTER(LLNodeQueue)
|
|
34
35
|
|
|
35
|
-
llqueue_lib.is_empty.argtypes = [POINTER(LLNodeQueue)]
|
|
36
|
-
llqueue_lib.is_empty.restype = c_bool
|
|
37
|
-
|
|
38
36
|
llqueue_lib.enqueue.argtypes = [POINTER(LLNodeQueue), py_object]
|
|
39
37
|
llqueue_lib.enqueue.restype = None
|
|
40
38
|
|
|
41
39
|
llqueue_lib.dequeue.argtypes = [POINTER(LLNodeQueue)]
|
|
42
40
|
llqueue_lib.dequeue.restype = py_object
|
|
43
41
|
|
|
42
|
+
llqueue_lib.clear_q.argtypes = [POINTER(LLNodeQueue)]
|
|
43
|
+
llqueue_lib.clear_q.restype = None
|
|
44
|
+
|
|
44
45
|
llqueue_lib.free_q.argtypes = [POINTER(LLNodeQueue)]
|
|
45
46
|
llqueue_lib.free_q.restype = None
|
|
46
47
|
|
|
@@ -52,9 +53,6 @@ class LLQueue:
|
|
|
52
53
|
def __init__(self):
|
|
53
54
|
self.queue = llqueue_lib.new_node_queue()
|
|
54
55
|
|
|
55
|
-
def is_empty(self) -> bool:
|
|
56
|
-
return llqueue_lib.is_empty(self.queue)
|
|
57
|
-
|
|
58
56
|
def __len__(self) -> int:
|
|
59
57
|
return self.queue.contents.length
|
|
60
58
|
|
|
@@ -62,44 +60,43 @@ class LLQueue:
|
|
|
62
60
|
llqueue_lib.enqueue(self.queue, item)
|
|
63
61
|
|
|
64
62
|
def dequeue(self) -> Any:
|
|
65
|
-
if self.is_empty():
|
|
66
|
-
raise IndexError
|
|
67
63
|
return llqueue_lib.dequeue(self.queue)
|
|
68
64
|
|
|
69
65
|
def clear(self):
|
|
70
|
-
llqueue_lib.
|
|
71
|
-
self.queue = llqueue_lib.new__queue()
|
|
66
|
+
llqueue_lib.clear_q(self.queue)
|
|
72
67
|
|
|
73
68
|
def __del__(self):
|
|
74
|
-
|
|
69
|
+
queue = getattr(self, "queue", None)
|
|
70
|
+
self.queue = None
|
|
71
|
+
llqueue_lib.free_q(queue)
|
|
75
72
|
|
|
76
73
|
|
|
77
74
|
# Matt's Contiguous Queue
|
|
78
75
|
class ContiguousQueue(Structure):
|
|
79
76
|
_fields_ = [
|
|
80
77
|
("objects", POINTER(py_object)),
|
|
81
|
-
("length",
|
|
82
|
-
("capacity",
|
|
83
|
-
("front",
|
|
84
|
-
("back",
|
|
78
|
+
("length", c_size_t),
|
|
79
|
+
("capacity", c_size_t),
|
|
80
|
+
("front", c_size_t),
|
|
81
|
+
("back", c_size_t),
|
|
85
82
|
]
|
|
86
83
|
|
|
87
84
|
|
|
88
85
|
__libfile = Path(__file__).parent / "ccqueue.so"
|
|
89
|
-
cqueue_lib =
|
|
86
|
+
cqueue_lib = PyDLL(str(__libfile))
|
|
90
87
|
|
|
91
88
|
cqueue_lib.new__queue.argtypes = []
|
|
92
89
|
cqueue_lib.new__queue.restype = POINTER(ContiguousQueue)
|
|
93
90
|
|
|
94
|
-
cqueue_lib.is_empty.argtypes = [POINTER(ContiguousQueue)]
|
|
95
|
-
cqueue_lib.is_empty.restype = c_bool
|
|
96
|
-
|
|
97
91
|
cqueue_lib.enqueue.argtypes = [POINTER(ContiguousQueue), py_object]
|
|
98
92
|
cqueue_lib.enqueue.restype = None
|
|
99
93
|
|
|
100
94
|
cqueue_lib.dequeue.argtypes = [POINTER(ContiguousQueue)]
|
|
101
95
|
cqueue_lib.dequeue.restype = py_object
|
|
102
96
|
|
|
97
|
+
cqueue_lib.clear_q.argtypes = [POINTER(ContiguousQueue)]
|
|
98
|
+
cqueue_lib.clear_q.restype = None
|
|
99
|
+
|
|
103
100
|
cqueue_lib.free_q.argtypes = [POINTER(ContiguousQueue)]
|
|
104
101
|
cqueue_lib.free_q.restype = None
|
|
105
102
|
|
|
@@ -111,9 +108,6 @@ class ContQueue:
|
|
|
111
108
|
def __init__(self):
|
|
112
109
|
self.queue = cqueue_lib.new__queue()
|
|
113
110
|
|
|
114
|
-
def is_empty(self) -> bool:
|
|
115
|
-
return cqueue_lib.is_empty(self.queue)
|
|
116
|
-
|
|
117
111
|
def __len__(self) -> int:
|
|
118
112
|
return self.queue.contents.length
|
|
119
113
|
|
|
@@ -121,13 +115,12 @@ class ContQueue:
|
|
|
121
115
|
cqueue_lib.enqueue(self.queue, item)
|
|
122
116
|
|
|
123
117
|
def dequeue(self) -> Any:
|
|
124
|
-
if self.is_empty():
|
|
125
|
-
raise IndexError
|
|
126
118
|
return cqueue_lib.dequeue(self.queue)
|
|
127
119
|
|
|
128
120
|
def clear(self):
|
|
129
|
-
cqueue_lib.
|
|
130
|
-
self.queue = cqueue_lib.new__queue()
|
|
121
|
+
cqueue_lib.clear_q(self.queue)
|
|
131
122
|
|
|
132
123
|
def __del__(self):
|
|
133
|
-
|
|
124
|
+
queue = getattr(self, "queue", None)
|
|
125
|
+
self.queue = None
|
|
126
|
+
cqueue_lib.free_q(queue)
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fastqueue-lib
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.18
|
|
4
4
|
Summary: Fast single ended queue library for python
|
|
5
5
|
Author-email: Matthew Taylor <matthew.taylor.andre@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/MatthewAndreTaylor/fastqueue
|
|
@@ -19,9 +19,14 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
20
|
Requires-Python: >=3.7
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
22
23
|
Provides-Extra: examples
|
|
24
|
+
Requires-Dist: matplotlib; extra == "examples"
|
|
25
|
+
Requires-Dist: numpy; extra == "examples"
|
|
26
|
+
Requires-Dist: pandas; extra == "examples"
|
|
23
27
|
Provides-Extra: tests
|
|
24
|
-
|
|
28
|
+
Requires-Dist: pytest; extra == "tests"
|
|
29
|
+
Dynamic: license-file
|
|
25
30
|
|
|
26
31
|
# fastqueue
|
|
27
32
|
|
|
@@ -31,7 +36,7 @@ License-File: LICENSE
|
|
|
31
36
|
[](https://pypi.org/project/fastqueue-lib/)
|
|
32
37
|
|
|
33
38
|
|
|
34
|
-
Single
|
|
39
|
+
Single-ended fast queues built in C tuned for Python.
|
|
35
40
|
|
|
36
41
|
## Requirements
|
|
37
42
|
|
|
@@ -39,7 +44,7 @@ Single ended fast queue's built in C tuned for python.
|
|
|
39
44
|
|
|
40
45
|
## Installation
|
|
41
46
|
|
|
42
|
-
To install fastqueue, using pip:
|
|
47
|
+
To install fastqueue, using [pip](https://pypi.org/project/fastqueue-lib):
|
|
43
48
|
|
|
44
49
|
```bash
|
|
45
50
|
pip install fastqueue-lib
|
|
@@ -93,9 +98,6 @@ True
|
|
|
93
98
|
['🚒', '🛴', '🚅', '🚗']
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
Another alternative is `fastqueue.LockQueue()` which supports all queue operations.
|
|
97
|
-
`fastqueue.LockQueue()` is built as a thread-safe alternative to the other queue types.
|
|
98
|
-
|
|
99
101
|
## Example Benchmarks
|
|
100
102
|
|
|
101
103
|
### Queue operations
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
MANIFEST.in
|
|
3
3
|
README.md
|
|
4
|
-
fastqueue.py
|
|
5
4
|
pyproject.toml
|
|
6
5
|
setup.py
|
|
7
6
|
fastqueue/__init__.py
|
|
7
|
+
fastqueue/__init__.pyi
|
|
8
8
|
fastqueue/prototypes.py
|
|
9
|
+
fastqueue/py.typed
|
|
9
10
|
fastqueue_lib.egg-info/PKG-INFO
|
|
10
11
|
fastqueue_lib.egg-info/SOURCES.txt
|
|
11
12
|
fastqueue_lib.egg-info/dependency_links.txt
|
|
@@ -14,4 +15,5 @@ fastqueue_lib.egg-info/top_level.txt
|
|
|
14
15
|
src/ccqueue.cpp
|
|
15
16
|
src/cllqueue.cpp
|
|
16
17
|
src/fastqueue.c
|
|
18
|
+
tests/test_memory.py
|
|
17
19
|
tests/test_queue.py
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2023 Matthew Andre Taylor
|
|
3
|
+
*/
|
|
4
|
+
#ifdef _WIN32
|
|
5
|
+
#define QUEUE_LIBRARY_API extern "C" __declspec(dllexport)
|
|
6
|
+
#else
|
|
7
|
+
#define QUEUE_LIBRARY_API extern "C"
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
#include <Python.h>
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
|
|
13
|
+
// Matt's C Contiguous Queue
|
|
14
|
+
QUEUE_LIBRARY_API typedef struct queue {
|
|
15
|
+
PyObject** objects;
|
|
16
|
+
size_t length;
|
|
17
|
+
size_t capacity;
|
|
18
|
+
size_t front;
|
|
19
|
+
size_t back;
|
|
20
|
+
} queue_t;
|
|
21
|
+
|
|
22
|
+
QUEUE_LIBRARY_API queue_t* new__queue() {
|
|
23
|
+
queue_t* queue = (queue_t*)malloc(sizeof(queue_t));
|
|
24
|
+
if (queue == NULL) {
|
|
25
|
+
PyErr_NoMemory();
|
|
26
|
+
return NULL;
|
|
27
|
+
}
|
|
28
|
+
queue->length = 0;
|
|
29
|
+
queue->capacity = 256;
|
|
30
|
+
queue->front = 0;
|
|
31
|
+
queue->back = queue->capacity - 1;
|
|
32
|
+
queue->objects = (PyObject**)malloc(256 * sizeof(PyObject*));
|
|
33
|
+
if (queue->objects == NULL) {
|
|
34
|
+
free(queue);
|
|
35
|
+
PyErr_NoMemory();
|
|
36
|
+
return NULL;
|
|
37
|
+
}
|
|
38
|
+
return queue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
int resize(queue_t* queue, size_t newCapacity) {
|
|
42
|
+
if (newCapacity > PY_SSIZE_T_MAX / sizeof(PyObject*)) {
|
|
43
|
+
PyErr_NoMemory();
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
PyObject** newObjects = (PyObject**)malloc(newCapacity * sizeof(PyObject*));
|
|
47
|
+
if (newObjects == NULL) {
|
|
48
|
+
PyErr_NoMemory();
|
|
49
|
+
return -1;
|
|
50
|
+
}
|
|
51
|
+
for (size_t i = 0; i < queue->length; ++i) {
|
|
52
|
+
newObjects[i] = queue->objects[(queue->front + i) % queue->capacity];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
free(queue->objects);
|
|
56
|
+
queue->objects = newObjects;
|
|
57
|
+
queue->front = 0;
|
|
58
|
+
queue->back = (queue->length + newCapacity - 1) % newCapacity;
|
|
59
|
+
queue->capacity = newCapacity;
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
QUEUE_LIBRARY_API void enqueue(queue_t* queue, PyObject* object) {
|
|
64
|
+
if (queue == NULL) {
|
|
65
|
+
PyErr_SetString(PyExc_RuntimeError, "Queue is not allocated");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (object == Py_None)
|
|
69
|
+
return;
|
|
70
|
+
|
|
71
|
+
if (queue->length == queue->capacity) {
|
|
72
|
+
if (queue->capacity > PY_SSIZE_T_MAX / sizeof(PyObject*) / 2) {
|
|
73
|
+
PyErr_NoMemory();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (resize(queue, queue->capacity ? queue->capacity * 2 : 256) < 0)
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
Py_INCREF(object);
|
|
81
|
+
queue->front = (queue->front + queue->capacity - 1) % queue->capacity;
|
|
82
|
+
queue->objects[queue->front] = object;
|
|
83
|
+
queue->length++;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
QUEUE_LIBRARY_API PyObject* dequeue(queue_t* queue) {
|
|
87
|
+
if (queue == NULL || queue->length == 0) {
|
|
88
|
+
PyErr_SetString(PyExc_IndexError, "dequeue from an empty queue");
|
|
89
|
+
return NULL;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
PyObject* object = queue->objects[queue->back];
|
|
93
|
+
queue->back = (queue->back + queue->capacity - 1) % queue->capacity;
|
|
94
|
+
queue->length--;
|
|
95
|
+
return object;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
QUEUE_LIBRARY_API void clear_q(queue_t* queue) {
|
|
99
|
+
if (queue == NULL || queue->length == 0) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
PyObject** objects = queue->objects;
|
|
104
|
+
size_t length = queue->length;
|
|
105
|
+
size_t capacity = queue->capacity;
|
|
106
|
+
size_t front = queue->front;
|
|
107
|
+
// Detach before decrefs so callbacks cannot overwrite the old payloads.
|
|
108
|
+
queue->objects = NULL;
|
|
109
|
+
queue->length = queue->capacity = queue->front = queue->back = 0;
|
|
110
|
+
for (size_t i = 0; i < length; ++i) {
|
|
111
|
+
Py_DECREF(objects[(front + i) % capacity]);
|
|
112
|
+
}
|
|
113
|
+
if (queue->objects == NULL) {
|
|
114
|
+
queue->objects = objects;
|
|
115
|
+
queue->capacity = capacity;
|
|
116
|
+
queue->front = 0;
|
|
117
|
+
queue->back = capacity - 1;
|
|
118
|
+
} else {
|
|
119
|
+
free(objects);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
QUEUE_LIBRARY_API void free_q(queue_t* queue) {
|
|
124
|
+
if (queue == NULL) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
clear_q(queue);
|
|
129
|
+
free(queue->objects);
|
|
130
|
+
free(queue);
|
|
131
|
+
}
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
#endif
|
|
9
9
|
|
|
10
10
|
#include <Python.h>
|
|
11
|
-
#include <stdio.h>
|
|
12
11
|
#include <stdlib.h>
|
|
13
12
|
|
|
14
13
|
// Matt's C Linked List Queue
|
|
@@ -26,8 +25,10 @@ QUEUE_LIBRARY_API typedef struct queue {
|
|
|
26
25
|
|
|
27
26
|
node_t* new_node(PyObject* object) {
|
|
28
27
|
node_t* node = (node_t*)malloc(sizeof(node_t));
|
|
29
|
-
if (node == NULL)
|
|
28
|
+
if (node == NULL) {
|
|
29
|
+
PyErr_NoMemory();
|
|
30
30
|
return NULL;
|
|
31
|
+
}
|
|
31
32
|
|
|
32
33
|
Py_INCREF(object);
|
|
33
34
|
node->object = object;
|
|
@@ -37,25 +38,27 @@ node_t* new_node(PyObject* object) {
|
|
|
37
38
|
|
|
38
39
|
QUEUE_LIBRARY_API queue_t* new_node_queue() {
|
|
39
40
|
queue_t* queue = (queue_t*)malloc(sizeof(queue_t));
|
|
41
|
+
if (queue == NULL) {
|
|
42
|
+
PyErr_NoMemory();
|
|
43
|
+
return NULL;
|
|
44
|
+
}
|
|
40
45
|
queue->front = NULL;
|
|
41
46
|
queue->back = NULL;
|
|
42
47
|
queue->length = 0;
|
|
43
48
|
return queue;
|
|
44
49
|
}
|
|
45
50
|
|
|
46
|
-
QUEUE_LIBRARY_API
|
|
51
|
+
QUEUE_LIBRARY_API void enqueue(queue_t* queue, PyObject* object) {
|
|
47
52
|
if (queue == NULL) {
|
|
48
|
-
|
|
49
|
-
return
|
|
53
|
+
PyErr_SetString(PyExc_RuntimeError, "Queue is not allocated");
|
|
54
|
+
return;
|
|
50
55
|
}
|
|
51
|
-
return queue->length == 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
QUEUE_LIBRARY_API void enqueue(queue_t* queue, PyObject* object) {
|
|
55
56
|
if (object == Py_None)
|
|
56
57
|
return;
|
|
57
58
|
|
|
58
59
|
node_t* node = new_node(object);
|
|
60
|
+
if (node == NULL)
|
|
61
|
+
return;
|
|
59
62
|
if (queue->back == NULL) {
|
|
60
63
|
queue->front = node;
|
|
61
64
|
queue->back = node;
|
|
@@ -67,8 +70,10 @@ QUEUE_LIBRARY_API void enqueue(queue_t* queue, PyObject* object) {
|
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
QUEUE_LIBRARY_API PyObject* dequeue(queue_t* queue) {
|
|
70
|
-
if (
|
|
73
|
+
if (queue == NULL || queue->length == 0) {
|
|
74
|
+
PyErr_SetString(PyExc_IndexError, "dequeue from an empty queue");
|
|
71
75
|
return NULL;
|
|
76
|
+
}
|
|
72
77
|
|
|
73
78
|
node_t* temp = queue->front;
|
|
74
79
|
PyObject* object = temp->object;
|
|
@@ -80,13 +85,16 @@ QUEUE_LIBRARY_API PyObject* dequeue(queue_t* queue) {
|
|
|
80
85
|
return object;
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
QUEUE_LIBRARY_API void
|
|
88
|
+
QUEUE_LIBRARY_API void clear_q(queue_t* queue) {
|
|
84
89
|
if (queue == NULL) {
|
|
85
|
-
perror("Queue not allocated");
|
|
86
90
|
return;
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
node_t* current = queue->front;
|
|
94
|
+
// Detach before decrefs so finalizers can safely reuse this queue.
|
|
95
|
+
queue->front = NULL;
|
|
96
|
+
queue->back = NULL;
|
|
97
|
+
queue->length = 0;
|
|
90
98
|
node_t* next;
|
|
91
99
|
while (current != NULL) {
|
|
92
100
|
next = current->next;
|
|
@@ -94,5 +102,13 @@ QUEUE_LIBRARY_API void free_q(queue_t* queue) {
|
|
|
94
102
|
free(current);
|
|
95
103
|
current = next;
|
|
96
104
|
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
QUEUE_LIBRARY_API void free_q(queue_t* queue) {
|
|
108
|
+
if (queue == NULL) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
clear_q(queue);
|
|
97
113
|
free(queue);
|
|
98
114
|
}
|