Jerry a raison, si c'est juste le Ctrl-C qui vous inquiète, vous pouvez ignorer le SIGINT pendant certaines périodes. Si vous voulez être à l'abri de la mort du processus en général, vous avez besoin d'une sorte de journalisation minimale. Afin d'échanger deux éléments :
1) Ajoutez un enregistrement dans une structure de contrôle à la fin du fichier ou dans un fichier séparé, indiquant les deux éléments du fichier que vous allez échanger, A et B.
2) Copiez A sur l'espace de grattage, enregistrez que vous l'avez fait, tirez la chasse.
3) Copiez B sur A, puis enregistrez dans l'espace scratch que vous l'avez fait, tirez la chasse.
4) Copier de l'espace scratch sur B.
5) Retirez l'enregistrement.
Il s'agit d'un espace supplémentaire de O(1) à toutes fins pratiques, ce qui compte toujours comme un espace en place selon la plupart des définitions. En théorie, l'enregistrement d'un index est O(log n) si n peut être arbitrairement grand : en réalité, c'est un très petit log n, et les limites raisonnables de matériel / temps d'exécution sont au-dessus de 64.
Dans tous les cas, quand je dis "flush", je veux dire valider les changements "suffisamment loin". Parfois, votre opération de purge de base ne fait que purger les tampons au sein du processus, mais elle ne synchronise pas réellement le support physique, car elle ne purge pas les tampons jusqu'aux niveaux du système d'exploitation, du pilote du périphérique et du matériel. C'est suffisant quand tout ce qui vous préoccupe est la mort du processus, mais si vous vous inquiétez d'un démontage brutal du support, vous devrez purger au-delà du pilote. Si vous vous inquiétez d'une panne de courant, vous devriez synchroniser le matériel, mais ce n'est pas le cas. Avec un onduleur ou si vous pensez que les coupures de courant sont si rares que cela ne vous dérange pas de perdre des données, c'est parfait.
Au démarrage, vérifiez l'espace d'effacement pour tout enregistrement de "swap-in-progress". Si vous en trouvez un, déterminez où vous en êtes et terminez l'échange à partir de là pour remettre les données dans un état sain. Puis recommencez votre tri.
Il est évident qu'il y a un problème de performance, puisque vous écrivez deux fois plus d'enregistrements qu'auparavant, et que les flushes/syncs peuvent être étonnamment coûteux. En pratique, votre tri in-place peut comporter des opérations de déplacement composées, impliquant de nombreux swaps, mais que vous pouvez optimiser pour éviter que chaque élément ne touche l'espace scratch. Vous devez simplement vous assurer qu'avant d'écraser une donnée, vous en avez une copie en sécurité quelque part et un enregistrement de l'endroit où cette copie doit aller afin de remettre votre fichier dans un état où il contient exactement une copie de chaque élément.
Jerry a également raison de dire qu'un véritable tri sur place est trop difficile et trop lent pour la plupart des besoins pratiques. Si vous pouvez épargner une fraction linéaire de la taille du fichier d'origine en tant qu'espace brouillon, vous aurez beaucoup plus de facilité avec un tri par fusion.
D'après vos précisions, vous n'auriez pas besoin d'opérations de vidage, même avec un tri sur place. Vous avez besoin d'un espace de grattage en mémoire qui fonctionne de la même manière et auquel votre gestionnaire SIGINT peut accéder afin d'obtenir des données sûres. avant quitter, plutôt que de restaurer au démarrage après une sortie anormale, et vous devez accéder à cette mémoire d'une manière sécurisée par rapport aux signaux (ce qui, techniquement, signifie utiliser un fichier de type sig_atomic_t
pour indiquer quelles modifications ont été apportées). Malgré cela, il est probablement préférable d'utiliser un mergesort plutôt qu'un véritable tri in-place.