mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-10-30 23:47:33 +03:00 
			
		
		
		
	Added a thread lock to the TcpClient
This gives multi-threading safety without giving up on speed (now there's no need for additional sleeps)
This commit is contained in:
		
							parent
							
								
									fd14a5a49a
								
							
						
					
					
						commit
						e47344c0f0
					
				|  | @ -14,14 +14,19 @@ from tl.all_tlobjects import tlobjects | |||
| 
 | ||||
| class MtProtoSender: | ||||
|     """MTProto Mobile Protocol sender (https://core.telegram.org/mtproto/description)""" | ||||
|     def __init__(self, transport, session): | ||||
|     def __init__(self, transport, session, check_updates_delay=0.1): | ||||
|         """If check_updates_delay is None, no updates will be checked. | ||||
|            Otherwise, specifies every how often updates should be checked""" | ||||
| 
 | ||||
|         self.transport = transport | ||||
|         self.session = session | ||||
| 
 | ||||
|         self.need_confirmation = []  # Message IDs that need confirmation | ||||
|         self.on_update_handlers = [] | ||||
| 
 | ||||
|         # Set up updates thread | ||||
|         # Set up updates thread, if the delay is not None | ||||
|         self.check_updates_delay = check_updates_delay | ||||
|         if check_updates_delay: | ||||
|             self.updates_thread = Thread(target=self.updates_thread_method, name='Updates thread') | ||||
|             self.updates_thread_running = True | ||||
|             self.updates_thread_paused = True | ||||
|  | @ -29,7 +34,7 @@ class MtProtoSender: | |||
|             self.updates_thread.start() | ||||
| 
 | ||||
|     def disconnect(self): | ||||
|         """Disconnects and **stops all the running threads**""" | ||||
|         """Disconnects and **stops all the running threads** if any""" | ||||
|         self.updates_thread_running = False | ||||
|         self.transport.cancel_receive() | ||||
|         self.transport.close() | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| # Python rough implementation of a C# TCP client | ||||
| import socket | ||||
| import time | ||||
| from threading import Lock | ||||
| 
 | ||||
| from errors import ReadCancelledError | ||||
| from utils import BinaryWriter | ||||
|  | @ -10,8 +11,11 @@ class TcpClient: | |||
|     def __init__(self): | ||||
|         self.connected = False | ||||
|         self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||||
| 
 | ||||
|         # Support for multi-threading advantages and safety | ||||
|         self.cancelled = False  # Has the read operation been cancelled? | ||||
|         self.delay = 0.1  # Read delay when there was no data available | ||||
|         self.lock = Lock() | ||||
| 
 | ||||
|     def connect(self, ip, port): | ||||
|         """Connects to the specified IP and port number""" | ||||
|  | @ -27,11 +31,18 @@ class TcpClient: | |||
| 
 | ||||
|     def write(self, data): | ||||
|         """Writes (sends) the specified bytes to the connected peer""" | ||||
| 
 | ||||
|         # Ensure that only one thread can send data at once | ||||
|         with self.lock: | ||||
|             self.socket.sendall(data) | ||||
| 
 | ||||
|     def read(self, buffer_size): | ||||
|         """Reads (receives) the specified bytes from the connected peer""" | ||||
|         self.cancelled = False  # Ensure it is not cancelled at first | ||||
| 
 | ||||
|         # Ensure that only one thread can receive data at once | ||||
|         with self.lock: | ||||
|             # Ensure it is not cancelled at first, so we can enter the loop | ||||
|             self.cancelled = False | ||||
| 
 | ||||
|             with BinaryWriter() as writer: | ||||
|                 while writer.written_count < buffer_size and not self.cancelled: | ||||
|  | @ -57,10 +68,9 @@ class TcpClient: | |||
|                                                   'was already read. This has not yet implemented ' | ||||
|                                                   'an internal buffer, so cannot continue.') | ||||
| 
 | ||||
|                 # If everything went fine, return the read bytes | ||||
|                 return writer.get_bytes() | ||||
| 
 | ||||
|     def cancel_read(self): | ||||
|         """Cancels the read operation if it was blocking and stops | ||||
|            the current thread until it's cancelled""" | ||||
|         """Cancels the read operation raising a ReadCancelledError""" | ||||
|         self.cancelled = True | ||||
|         time.sleep(self.delay) | ||||
|  |  | |||
|  | @ -60,8 +60,8 @@ class TcpTransport: | |||
|             self.tcp_client.close() | ||||
| 
 | ||||
|     def cancel_receive(self): | ||||
|         """Cancels (stops) trying to receive from the remote peer and | ||||
|            stops the current thread until it's cancelled""" | ||||
|         """Cancels (stops) trying to receive from the | ||||
|         remote peer and raises a ReadCancelledError""" | ||||
|         self.tcp_client.cancel_read() | ||||
| 
 | ||||
|     def get_client_delay(self): | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user