Skip to content

Commit b5c4ec4

Browse files
committed
Intermediate changes
1 parent 88fb7b5 commit b5c4ec4

File tree

13 files changed

+1564
-675
lines changed

13 files changed

+1564
-675
lines changed

contrib/libs/cxxsupp/libcxxmsvc/include/__support/win32/atomic_win32.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ void __msvc_unlock(void* p);
8686

8787
template<class _Out, class _Tp>
8888
static inline _Out __msvc_cast(_Tp __val) {
89-
_Out __result;
89+
alignas(_Out) char __result[sizeof(_Out)];
9090
volatile char* to = reinterpret_cast<volatile char*>(&__result);
9191
volatile char* end = to + sizeof(_Tp);
9292
char* from = reinterpret_cast<char*>(&__val);
9393
while (to != end) {
9494
*to++ = *from++;
9595
}
96-
return __result;
96+
return *reinterpret_cast<_Out*>(&__result);
9797
}
9898

9999

@@ -368,21 +368,20 @@ static inline __int64 __msvc_atomic_load64(volatile __int64* __a, memory_order _
368368

369369
template<typename _Tp>
370370
static inline _Tp __c11_atomic_load(volatile _Atomic(_Tp)* __a, int __order) {
371-
_Tp __result;
372371
if (sizeof(_Tp) == 1) {
373-
__result = __msvc_cast<_Tp>(__msvc_atomic_load8((volatile char*)__a, (memory_order)__order));
372+
return __msvc_cast<_Tp>(__msvc_atomic_load8((volatile char*)__a, (memory_order)__order));
374373
} else if (sizeof(_Tp) == 2 && alignof(_Tp) % 2 == 0) {
375-
__result = __msvc_cast<_Tp>(__msvc_atomic_load16((volatile short*)__a, (memory_order)__order));
374+
return __msvc_cast<_Tp>(__msvc_atomic_load16((volatile short*)__a, (memory_order)__order));
376375
} else if (sizeof(_Tp) == 4 && alignof(_Tp) % 4 == 0) {
377-
__result = __msvc_cast<_Tp>(__msvc_atomic_load32((volatile long*)__a, (memory_order)__order));
376+
return __msvc_cast<_Tp>(__msvc_atomic_load32((volatile long*)__a, (memory_order)__order));
378377
} else if (sizeof(_Tp) == 8 && alignof(_Tp) % 8 == 0) {
379-
__result = __msvc_cast<_Tp>(__msvc_atomic_load64((volatile __int64*)__a, (memory_order)__order));
378+
return __msvc_cast<_Tp>(__msvc_atomic_load64((volatile __int64*)__a, (memory_order)__order));
380379
} else {
381380
__msvc_lock((void*)__a);
382-
__result = *(_Atomic(_Tp)*)__a;
381+
_Tp __result = *(_Atomic(_Tp)*)__a;
383382
__msvc_unlock((void*)__a);
383+
return __result;
384384
}
385-
return __result;
386385
}
387386

388387
template<typename _Tp>
Lines changed: 186 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,198 @@
11
Metadata-Version: 2.1
22
Name: Automat
3-
Version: 22.10.0
3+
Version: 24.8.0
44
Summary: Self-service finite-state machines for the programmer on the go.
5-
Home-page: https://github.com/glyph/Automat
6-
Author: Glyph
7-
Author-email: glyph@twistedmatrix.com
8-
License: MIT
9-
Keywords: fsm finite state machine automata
5+
Author-email: Glyph <code@glyph.im>
6+
License: Copyright (c) 2014
7+
Rackspace
8+
9+
Permission is hereby granted, free of charge, to any person obtaining
10+
a copy of this software and associated documentation files (the
11+
"Software"), to deal in the Software without restriction, including
12+
without limitation the rights to use, copy, modify, merge, publish,
13+
distribute, sublicense, and/or sell copies of the Software, and to
14+
permit persons to whom the Software is furnished to do so, subject to
15+
the following conditions:
16+
17+
The above copyright notice and this permission notice shall be
18+
included in all copies or substantial portions of the Software.
19+
20+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+
28+
Project-URL: Documentation, https://automat.readthedocs.io/
29+
Project-URL: Source, https://github.com/glyph/automat/
30+
Keywords: fsm,state machine,automata
1031
Classifier: Intended Audience :: Developers
1132
Classifier: License :: OSI Approved :: MIT License
1233
Classifier: Operating System :: OS Independent
1334
Classifier: Programming Language :: Python
14-
Classifier: Programming Language :: Python :: 2
15-
Classifier: Programming Language :: Python :: 2.7
1635
Classifier: Programming Language :: Python :: 3
17-
Classifier: Programming Language :: Python :: 3.5
18-
Classifier: Programming Language :: Python :: 3.6
19-
Classifier: Programming Language :: Python :: 3.7
2036
Classifier: Programming Language :: Python :: 3.8
37+
Classifier: Programming Language :: Python :: 3.9
38+
Classifier: Programming Language :: Python :: 3.10
39+
Classifier: Programming Language :: Python :: 3.11
40+
Classifier: Programming Language :: Python :: 3.12
41+
Description-Content-Type: text/markdown
2142
License-File: LICENSE
22-
Requires-Dist: attrs (>=19.2.0)
23-
Requires-Dist: six
43+
Requires-Dist: typing-extensions; python_version < "3.10"
2444
Provides-Extra: visualize
25-
Requires-Dist: graphviz (>0.5.1) ; extra == 'visualize'
26-
Requires-Dist: Twisted (>=16.1.1) ; extra == 'visualize'
45+
Requires-Dist: graphviz>0.5.1; extra == "visualize"
46+
Requires-Dist: Twisted>=16.1.1; extra == "visualize"
2747

48+
# Automat #
49+
50+
[![Documentation Status](https://readthedocs.org/projects/automat/badge/?version=latest)](http://automat.readthedocs.io/en/latest/)
51+
[![Build Status](https://github.com/glyph/automat/actions/workflows/ci.yml/badge.svg?branch=trunk)](https://github.com/glyph/automat/actions/workflows/ci.yml?query=branch%3Atrunk)
52+
[![Coverage Status](http://codecov.io/github/glyph/automat/coverage.svg?branch=trunk)](http://codecov.io/github/glyph/automat?branch=trunk)
53+
54+
## Self-service finite-state machines for the programmer on the go. ##
55+
56+
Automat is a library for concise, idiomatic Python expression of finite-state
57+
automata (particularly deterministic finite-state transducers).
58+
59+
Read more here, or on [Read the Docs](https://automat.readthedocs.io/), or watch the following videos for an overview and presentation
60+
61+
### Why use state machines? ###
62+
63+
Sometimes you have to create an object whose behavior varies with its state,
64+
but still wishes to present a consistent interface to its callers.
65+
66+
For example, let's say you're writing the software for a coffee machine. It
67+
has a lid that can be opened or closed, a chamber for water, a chamber for
68+
coffee beans, and a button for "brew".
69+
70+
There are a number of possible states for the coffee machine. It might or
71+
might not have water. It might or might not have beans. The lid might be open
72+
or closed. The "brew" button should only actually attempt to brew coffee in
73+
one of these configurations, and the "open lid" button should only work if the
74+
coffee is not, in fact, brewing.
75+
76+
With diligence and attention to detail, you can implement this correctly using
77+
a collection of attributes on an object; `hasWater`, `hasBeans`, `isLidOpen`
78+
and so on. However, you have to keep all these attributes consistent. As the
79+
coffee maker becomes more complex - perhaps you add an additional chamber for
80+
flavorings so you can make hazelnut coffee, for example - you have to keep
81+
adding more and more checks and more and more reasoning about which
82+
combinations of states are allowed.
83+
84+
Rather than adding tedious `if` checks to every single method to make sure that
85+
each of these flags are exactly what you expect, you can use a state machine to
86+
ensure that if your code runs at all, it will be run with all the required
87+
values initialized, because they have to be called in the order you declare
88+
them.
89+
90+
You can read about state machines and their advantages for Python programmers
91+
in more detail [in this excellent article by Jean-Paul
92+
Calderone](https://web.archive.org/web/20160507053658/https://clusterhq.com/2013/12/05/what-is-a-state-machine/).
93+
94+
### What makes Automat different? ###
95+
96+
There are
97+
[dozens of libraries on PyPI implementing state machines](https://pypi.org/search/?q=finite+state+machine).
98+
So it behooves me to say why yet another one would be a good idea.
99+
100+
Automat is designed around this principle: while organizing your code around
101+
state machines is a good idea, your callers don't, and shouldn't have to, care
102+
that you've done so. In Python, the "input" to a stateful system is a method
103+
call; the "output" may be a method call, if you need to invoke a side effect,
104+
or a return value, if you are just performing a computation in memory. Most
105+
other state-machine libraries require you to explicitly create an input object,
106+
provide that object to a generic "input" method, and then receive results,
107+
sometimes in terms of that library's interfaces and sometimes in terms of
108+
classes you define yourself.
109+
110+
For example, a snippet of the coffee-machine example above might be implemented
111+
as follows in naive Python:
112+
113+
```python
114+
class CoffeeMachine(object):
115+
def brewButton(self) -> None:
116+
if self.hasWater and self.hasBeans and not self.isLidOpen:
117+
self.heatTheHeatingElement()
118+
# ...
119+
```
120+
121+
With Automat, you'd begin with a `typing.Protocol` that describes all of your
122+
inputs:
123+
124+
```python
125+
from typing import Protocol
126+
127+
class CoffeeBrewer(Protocol):
128+
def brewButton(self) -> None:
129+
"The user pressed the 'brew' button."
130+
def putInBeans(self) -> None:
131+
"The user put in some beans."
132+
```
133+
134+
We'll then need a concrete class to contain the shared core of state shared
135+
among the different states:
136+
137+
```python
138+
from dataclasses import dataclass
139+
140+
@dataclass
141+
class BrewerCore:
142+
heatingElement: HeatingElement
143+
```
144+
145+
Next, we need to describe our state machine, including all of our states. For
146+
simplicity's sake let's say that the only two states are `noBeans` and
147+
`haveBeans`:
148+
149+
```python
150+
from automat import TypeMachineBuilder
151+
152+
builder = TypeMachineBuilder(CoffeeBrewer, BrewerCore)
153+
noBeans = builder.state("noBeans")
154+
haveBeans = builder.state("haveBeans")
155+
```
156+
157+
Next we can describe a simple transition; when we put in beans, we move to the
158+
`haveBeans` state, with no other behavior.
159+
160+
```python
161+
# When we don't have beans, upon putting in beans, we will then have beans
162+
noBeans.upon(CoffeeBrewer.putInBeans).to(haveBeans).returns(None)
163+
```
164+
165+
And then another transition that we describe with a decorator, one that *does*
166+
have some behavior, that needs to heat up the heating element to brew the
167+
coffee:
168+
169+
```python
170+
@haveBeans.upon(CoffeeBrewer.brewButton).to(noBeans)
171+
def heatUp(inputs: CoffeeBrewer, core: BrewerCore) -> None:
172+
"""
173+
When we have beans, upon pressing the brew button, we will then not have
174+
beans any more (as they have been entered into the brewing chamber) and
175+
our output will be heating the heating element.
176+
"""
177+
print("Brewing the coffee...")
178+
core.heatingElement.turnOn()
179+
```
180+
181+
Then we finalize the state machine by building it, which gives us a callable
182+
that takes a `BrewerCore` and returns a synthetic `CoffeeBrewer`
183+
184+
```python
185+
newCoffeeMachine = builder.build()
186+
```
187+
188+
```python
189+
>>> coffee = newCoffeeMachine(BrewerCore(HeatingElement()))
190+
>>> machine.putInBeans()
191+
>>> machine.brewButton()
192+
Brewing the coffee...
193+
```
194+
195+
All of the *inputs* are provided by calling them like methods, all of the
196+
*output behaviors* are automatically invoked when they are produced according
197+
to the outputs specified to `upon` and all of the states are simply opaque
198+
tokens.

0 commit comments

Comments
 (0)